I am new to React and I am trying to make a sample SPA whereby the different components I created are linked using React-Router. One of my components is dynamically created and is not being rendered properly.
How do I fix it? Here is the code on codepen the link to the pen. The issue here is that the dynamically created circles are not being created with the yellow background.
import * as React from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";
import {BrowserRouter,Link,Switch,Route} from "https://cdn.skypack.dev/react-router-dom@5.2.0";
function App() {
return (
<div
style={{
backgroundColor: "yellow",
padding: 20
}}
>
<h1>Simple SPA</h1>
<header>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="lightningcard">Lightning Card</Link>
</li>
<li>
<Link to="circles">Circles</Link>
</li>
<li>
<Link to="clickcounter">Click Counter</Link>
</li>
<li>
<Link to="colordisplay">Color Display</Link>
</li>
</ul>
</header>
<Switch>
<Route exact path="/" component={Home}></Route>
<Route exact path="/lightningcard" component={LightningCard}></Route>
<Route exact path="/circles" component={Circles}></Route>
<Route exact path="/clickcounter" component={ClickCounter}></Route>
<Route exact path="/colordisplay" component={ColorDisplay}></Route>
</Switch>
</div>
);
}
function Home() {
return (
<div className="home">
<h2>HELLO</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed consequat
velit vitae mollis facilisis. Praesent consectetur risus sapien, ac
porta sapien consequat vitae. Aliquam erat volutpat. Mauris ut elit
ante. Donec ligula ante, iaculis et malesuada sit amet, faucibus id ex.
Ut venenatis eros eget quam venenatis auctor. Ut pulvinar quam eros, in
tempor eros scelerisque eu. Ut porttitor dictum mi nec fermentum. In
ultrices pretium lacus, nec malesuada arcu pharetra ut.
</p>
</div>
);
}
function Letter(props) {
let bgColor = props.bgColor;
let letterStyle = {
backgroundColor: bgColor,
display: "inline-block",
fontFamily: "monospace",
width: 20,
height: 30,
padding: 20,
margin: 20,
textAlign: "center",
fontSize: 32
};
return <div style={letterStyle}>{props.children}</div>;
}
function Card(props) {
let cardStyle = {
width: 200,
height: 250,
margin: 40,
display: "inline-block",
backgroundColor: "white",
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #333)"
};
return (
<div style={cardStyle}>
<ColorPanel color={props.color}></ColorPanel>
<ColorLabel label={props.color}></ColorLabel>
</div>
);
}
function ColorPanel(props) {
let colorPanelStyle = {
backgroundColor: props.color,
width: 200,
height: 200
};
return <div style={colorPanelStyle}></div>;
}
function ColorLabel(props) {
let colorLabelStyle = {
fontFamily: "monospace",
fontSize: 35,
textAlign: "center",
textTransform: "uppercase"
};
return <div style={colorLabelStyle}>{props.label}</div>;
}
function LightningCard() {
let lightningCardStyle = {
backgroundColor: "black",
borderRadius: 10,
padding: 40,
color: "#999",
textAlign: "center",
width: 250
};
let commonStyles = {
padding: 0,
margin: 0,
textTransform: "uppercase"
};
let style1 = {
...commonStyles,
fontSize: 28
};
let style2 = {
...commonStyles,
fontSize: 42
};
let style3 = {
...commonStyles,
textTransform: "lowercase",
fontSize: 18,
opacity: 0.5
};
return (
<div style={lightningCardStyle}>
<LightningCount></LightningCount>
<div>
<div style={style1}>Lightning Strikes</div>
<div style={style2}>Worldwide</div>
<div style={style3}>(since you loaded this example)</div>
</div>
</div>
);
}
class LightningCount extends React.Component {
constructor() {
super();
this.state = { count: 0 };
this.strike = this.strike.bind(this);
}
strike() {
this.setState({ count: this.state.count + 1 });
}
componentDidMount() {
this.timer = setInterval(this.strike, 100);
}
componentWillUnmount() {
clearInterval(this.timer);
}
lightningCountStyle = {
textAlign: "center",
color: "aqua",
fontWeight: "bold",
fontSize: 60
};
render() {
return <div style={this.lightningCountStyle}>{this.state.count}</div>;
}
}
function Circle(props) {
let circleStyle = {
borderRadius: 50,
display: "inline-block",
width: 100,
height: 100,
backgroundColor: props.color,
color: props.color,
margin: 20,
float: "left"
};
return <div style={circleStyle}></div>;
}
class Circles extends React.Component {
constructor(props) {
super(props);
this.state = { circles: [] };
this.createCircles = this.createCircles.bind(this);
}
componentDidMount() {
this.interval = setInterval(this.createCircles, 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
circles = [];
createCircles() {
if (this.circles.length >= 5) {
clearInterval(this.interval);
}
let r = Math.floor(Math.random() * 256),
g = Math.floor(Math.random() * 256),
b = Math.floor(Math.random() * 256);
let color = `rgb(${r},${g},${b})`;
this.circles.push(
<Circle color={color.toString()} key={this.circles.length}></Circle>
);
this.setState({ circles: this.circles });
}
render() {
return <div>{this.state.circles}</div>;
}
}
class ClickCounter extends React.Component {
constructor() {
super();
this.handleClick = this.handleClick.bind(this);
this.state = { count: 0 };
}
render() {
let buttonStyle = {
width: 30,
height: 30,
fontFamily: "sans-serif",
color: "#333",
fontWeight: "bold",
lineHeight: "3px"
};
let countStyle = {
fontSize: 108,
fontWeight: "bold",
textAlign: "center",
fontFamily: "sans-serif"
};
let clickCounterDisplayStyle = {
width: 350,
height: 200,
borderRadius: 10,
backgroundColor: "#FFC53A",
textAlign: "center"
};
return (
<div style={clickCounterDisplayStyle}>
<div style={countStyle}>{this.state.count}</div>
<button style={buttonStyle} onClick={this.handleClick}>
+
</button>
</div>
);
}
handleClick() {
this.setState({ count: this.state.count + 1 });
}
}
class ColorDisplay extends React.Component {
constructor(props) {
super(props);
this.state = {
color: "green"
};
this.textInputElement = React.createRef();
this.changeColor = this.changeColor.bind(this);
}
changeColor(e) {
let color = this.textInputElement.current.value;
this.setState({
color: color
});
e.preventDefault();
this.textInputElement.current.value = "";
this.textInputElement.current.focus();
}
render() {
let colorPanelStyle = {
WebkitFilter: "drop-shadow(0px 0px 5px #666)",
filter: "drop-shadow(0px 0px 5px #333)"
};
let colorDisplayStyle = {
width: 200,
height: 250
};
let textInputStyle = {
padding: 10,
margin: "10px 5px 0px 0px",
width: 120
};
let buttonStyle = {
padding: 10,
color: "white",
backgroundColor: "#666",
border: "1px solid #666"
};
return (
<form style={colorDisplayStyle} onSubmit={this.changeColor}>
<ColorPanel
color={this.state.color}
style={colorPanelStyle}
></ColorPanel>
<input
style={textInputStyle}
ref={this.textInputElement}
placeholder="Enter a color value"
type="text"
/>
<button style={buttonStyle}>GO</button>
</form>
);
}
}
ReactDOM.render(
<BrowserRouter>
<Route path="/" component={App}></Route>
</BrowserRouter>,
document.getElementById("root")
);
question from:
https://stackoverflow.com/questions/65918853/issues-rendering-dynamic-list-of-components-properly-in-react