最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Component State issue with duplicate components - Stack Overflow

programmeradmin2浏览0评论

I've recently started learning React and I'm a little bit confused.

Please see the following codepen or the code snippet below.

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      sessions: [],
      sessionSelected: null
    }
    this.addSession = this.addSession.bind(this);
    this.switchSession = this.switchSession.bind(this);
  }

  addSession() {
    let sessions = this.state.sessions;
    let id = (sessions.length)
    let title = "Session " + id;
    let session = <Session title={title} index={id + 1} />;
    sessions.push(session);
    this.setState({
      sessions: sessions,
      sessionSelected: id
    });
  }

  switchSession(id) {
    this.setState({
      sessionSelected: id
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.addSession} >+ Add Session</button>
        <div>{this.state.sessions[this.state.sessionSelected]}</div>
        <div className="switchers">
          {this.state.sessions.map((x, i) => {
            return <SessionSwitcher index={i + 1} onClick={() => { this.switchSession(i) }} />;
          })}
        </div>
      </div>
    );
  }
}

class Session extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
    this.startTimer = this.startTimer.bind(this);
    this.count = this.count.bind(this);
  }
  startTimer() {
    setInterval(this.count, 1000);
  }
  count() {
    this.setState({
      count: this.state.count + 1
    });
  }
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.state.count}</p>
        <button onClick={this.startTimer}>Start Timer</button>
      </div>
    )
  }
}

class SessionSwitcher extends React.Component {
  render() {
    return (
      <div className="switcher" onClick={this.props.onClick}>
        <span>{this.props.index}</span>
      </div>
    )
  }
}

ReactDOM.render(
  <App />,
  document.querySelector('#app')
);

I want to be able to trigger multiple timers within multiple ponents.

For some reason when I click the start timer in one ponent, it triggers it for the other ponents too.

Can someone explain to me what I am doing wrong?

I've recently started learning React and I'm a little bit confused.

Please see the following codepen or the code snippet below.

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      sessions: [],
      sessionSelected: null
    }
    this.addSession = this.addSession.bind(this);
    this.switchSession = this.switchSession.bind(this);
  }

  addSession() {
    let sessions = this.state.sessions;
    let id = (sessions.length)
    let title = "Session " + id;
    let session = <Session title={title} index={id + 1} />;
    sessions.push(session);
    this.setState({
      sessions: sessions,
      sessionSelected: id
    });
  }

  switchSession(id) {
    this.setState({
      sessionSelected: id
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.addSession} >+ Add Session</button>
        <div>{this.state.sessions[this.state.sessionSelected]}</div>
        <div className="switchers">
          {this.state.sessions.map((x, i) => {
            return <SessionSwitcher index={i + 1} onClick={() => { this.switchSession(i) }} />;
          })}
        </div>
      </div>
    );
  }
}

class Session extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
    this.startTimer = this.startTimer.bind(this);
    this.count = this.count.bind(this);
  }
  startTimer() {
    setInterval(this.count, 1000);
  }
  count() {
    this.setState({
      count: this.state.count + 1
    });
  }
  render() {
    return (
      <div>
        <h1>{this.props.title}</h1>
        <p>{this.state.count}</p>
        <button onClick={this.startTimer}>Start Timer</button>
      </div>
    )
  }
}

class SessionSwitcher extends React.Component {
  render() {
    return (
      <div className="switcher" onClick={this.props.onClick}>
        <span>{this.props.index}</span>
      </div>
    )
  }
}

ReactDOM.render(
  <App />,
  document.querySelector('#app')
);

I want to be able to trigger multiple timers within multiple ponents.

For some reason when I click the start timer in one ponent, it triggers it for the other ponents too.

Can someone explain to me what I am doing wrong?

Share Improve this question edited Oct 5, 2018 at 16:11 Alexis Wilke 20.9k11 gold badges106 silver badges179 bronze badges asked Feb 9, 2018 at 0:14 jastewjastew 3233 silver badges10 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

Here are a couple of things you could change to get a more predictable experience:

  1. Rather than storing JSX in state, which is a plex object, store just the id, and render JSX according to that id.

  2. Try not to mutate state in place (as with pushing onto an array that's already in state).

  3. If you want to have persistent timers across ponents, regardless of which ones are currently selected, be sure not to unmount them when they're deselected.

Here are the relevant updated parts of your <App/> ponent (note that these are more quick fixes than best practices):

  addSession() {
    const id = this.state.sessions.length;
    this.setState( state => ({
      // treat your state as immutable
      sessions: state.sessions.concat( id ),
      sessionSelected: id
    }));
  }

  // don't unmount when switching ponents, just hide
  render() {
    return (
      <div>
        <button onClick={this.addSession} >+ Add Session</button>
        <div>
          { this.state.sessions.map( session => 
            <div style={{ display: session === this.state.sessionSelected ? 'block' : 'none' }}>
              <Session title={"Session " + session} />
            </div>
          )}
        </div>
        <div className="switchers">
          {this.state.sessions.map((x, i) => {
            return <SessionSwitcher index={i + 1} onClick={() => { this.switchSession(i) }} />;
          })}
        </div>
      </div>
    );
  }

Try it here: https://codepen.io/glortho/pen/ZrLMda?editors=0011

发布评论

评论列表(0)

  1. 暂无评论