Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
132 views
in Technique[技术] by (71.8m points)

javascript - Issues rendering dynamic list of components properly in react

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/[email protected]";
import * as ReactDOM from "https://cdn.skypack.dev/[email protected]";
import {BrowserRouter,Link,Switch,Route} from "https://cdn.skypack.dev/[email protected]";

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your problem is the float: "left" in your circleStyle object. This takes the component out of the normal flow. If you remove that, the parents styles apply.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...