之前我们通过 props 的特性传递 Counters 组件的 state 到 Counter 组件中,因为这两个组件之间是上下层关系。但是这里我们可以看到,在 Counters 组件和 NavBar 组件之间没有父子关系,那我们怎么在 NavBar 中显示 Counters 的数量呢?
这种情况下,在两个组件之间没有上下父子级别的关系,我们又想让它们之间共享和同步数据时,我们需要将数据上移。将 counters[] 上移到它们共同的父级 App 组件中。
因为 Counters 和 NavBar 都有同一个父级组件,我们可以让 App 所有的子组件全部使用 props 。
我们来看看怎么上移 state :
我们需要将 Counters 的 state 和所有操作这个 state 的方法,移到它的父组件,也就是 App 组件中。
对于 Counters 中使用了已经被上移的引用时,我们需要在父组件中使用 props 下移它。
class App extends Component {
state = {
counters: [
{ id: 1,value: 4 },
{ id: 2,value: 0 },
{ id: 3,value: 0 },
{ id: 4,value: 0 }
]
}
handleReset = () => {
const counters = this.state.counters.map(c => {
c.value = 0;
return c;
})
this.setState({ counters });
}
handleIncrement = counter => {
const counters = [...this.state.counters];
const index = counters.indexOf(counter);
counters[index] = {...counter};
counters[index].value++;
this.setState({ counters })
}
handleDelete = (counterId) => {
const counters = this.state.counters.filter(c => c.id !== counterId);
this.setState({ counters });
}
render() {
return (
<React.Fragment>
<NavBar totalCounters={this.state.counters.filter(c => c.value > 0).length}/>
<main className="container">
<Counters
counters={this.state.counters}
onReset={this.handleReset}
onIncrement={this.handleIncrement}
onDelete={this.handleDelete}
/>
</main>
</React.Fragment>
);
}
}
class Counters extends Component {
render() {
return (<div>
<button
onClick={this.props.onReset}
className="btn btn-primary btn-sm m-2">Reset</button>
{ this.props.counters.map(counter =>
<Counter
key={counter.id}
onDelete={this.props.onDelete}
onIncrement={this.props.onIncrement}
counter={counter}/>
)}
</div>);
}
}
这样,我们就实现了通过 props 与所有的子组件共享数据。