使用重复的组件

时间:2018-02-09 00:14:18

标签: javascript reactjs

我最近开始学习React,我有点困惑。

请参阅以下codepen或下面的代码段。

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')
);

我希望能够在多个组件中触发多个计时器。

出于某种原因,当我在一个组件中单击启动计时器时,它也会为其他组件触发它。

有人可以向我解释我做错了吗?

1 个答案:

答案 0 :(得分:2)

以下是您可以更改的一些内容,以获得更可预测的体验:

  1. 不是将JSX存储在一个复杂对象的状态中,而是只存储id,并根据该id渲染JSX。

  2. 尽量不要在适当的位置改变状态(就像<App/>到已经处于状态的数组一样。)

  3. 如果您希望跨组件拥有持久性计时器,无论当前选择哪个计时器,请确保在取消选择它们时不要卸载它们。

  4. 以下是 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 components, 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> ); } 组件的相关更新部分(请注意,这些是比最佳做法更快的解决方案):

    /* @flow */
    type Person = {|
        firstName: string,
        lastName: string
    |};
    
    const transform = (person: Person): { ...Person, nameDisplay: string } => {
      // If you'd rather use Object.assign instead of spread syntax
      // return Object.assign({}, person, { nameDisplay: `${person.firstName} + ${person.lastName}` })
      return {
        ...person,
        nameDisplay: `${person.firstName} + ${person.lastName}`
      }
    }
    

    在此处试试:https://codepen.io/glortho/pen/ZrLMda?editors=0011