我最近开始学习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')
);
我希望能够在多个组件中触发多个计时器。
出于某种原因,当我在一个组件中单击启动计时器时,它也会为其他组件触发它。
有人可以向我解释我做错了吗?
答案 0 :(得分:2)
以下是您可以更改的一些内容,以获得更可预测的体验:
不是将JSX存储在一个复杂对象的状态中,而是只存储id,并根据该id渲染JSX。
尽量不要在适当的位置改变状态(就像<App/>
到已经处于状态的数组一样。)
如果您希望跨组件拥有持久性计时器,无论当前选择哪个计时器,请确保在取消选择它们时不要卸载它们。
以下是 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}`
}
}