javascript - React 中的状态应该提升多高?
问题描述
中间组件应该控制状态的一部分并调用传递给它们的道具还是应该将状态提升到更高的位置?我一直在来回考虑是让子组件利用本地状态还是让更高的组件处理它并向下传递额外的道具。
在这个有限的例子中,我有一个Main
组件。我在这个组件中显示一些数据并传递函数来过滤数据到子组件。但是,主要组件不一定需要知道menuOpen
属性何时更改。但是,我需要在、和被调用menuOpen
时更新。handleCancel()
handleSave()
handleButtonClick()
handleCancel()
并且handleSave()
都修改了显示的数据,因此我在Main
组件中声明了它们。
我应该props
从Main
组件传递所有这些,还是使用中间组件来处理较小部分的本地状态,但也要props
从父(祖父等)组件调用?
主要部件
//Parent component
class Main extends React.Component {
constructor() {
super();
this.state = {
checkBoxes: {
1: {
name: 'Apple',
isChecked: true,
},
//...
},
fruit: {
1: {
name: 'Apple',
},
//...
},
checkedBoxes: [],
};
this.baseState = JSON.stringify(this.state.checkBoxes);
this.fruitFilter = this.fruitFilter.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handleChange = this.handleChange.bind(this);
this.resetState = this.resetState.bind(this);
}
resetState() {
this.setState({checkBoxes: JSON.parse(this.baseState)});
}
//populates the checkedboxs array with name to filter by
handleSave() {
const checkedBoxes = Object.keys(this.state.checkBoxes)
.filter(key => {
//....some logic
});
this.baseState = JSON.stringify(this.state.checkBoxes);
this.setState({checkedBoxes: checkedBoxes});
}
//handles the checkbox toggle
handleChange(e) {
const checkBoxes = {...this.state.checkBoxes};
checkBoxes[e.target.id].isChecked = e.target.checked;
this.setState({checkBoxes: checkBoxes});
}
//filteres the fruit - if nothing is checked return them all
fruitFilter(fruit) {
return Object.keys(fruit)
.filter(key => {
//...filter logic
})
}
render() {
const visibleFruits = this.fruitFilter(this.state.fruit);
return (
<div>
<Filter
resetState={this.resetState}
checkBoxes={this.state.checkBoxes}
handleSave={this.handleSave}
handleChange={this.handleChange}
/>
<div>
<h2>Filtered Fruit</h2>
{Object.keys(visibleFruits).map(key => {
return (
//... renders list of fruit
);
})}
</div>
</div>
);
}
}
子组件
class Filter extends React.Component {
constructor(props) {
super(props);
this.state = {
menoOpen: false,
};
this.handleCancel = this.handleCancel.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleSave() {
this.setState({menuOpen: false});
this.props.handleSave();
}
handleCancel() {
this.setState({menuOpen: false});
this.props.resetState();
}
handleButtonClick() {
this.setState({menuOpen: !this.state.menuOpen});
}
render() {
return (
<div>
<button onClick={this.handleButtonClick}>Choose Fruits</button>
{this.state.menuOpen && (
<FilterMenu
checkBoxes={this.props.checkBoxes}
handleSave={this.handleSave}
handleCancel={this.handleCancel}
handleChange={this.props.handleChange}
/>
)}
</div>
);
}
}
孙子组件
const FilterMenu = ({checkBoxes, handleChange, handleCancel, handleSave}) => {
return (
<div>
{Object.keys(checkBoxes).map(key => {
return (
//... renders dropdown menu
);
})}
<button onClick={handleCancel}>Cancel</button>
<button onClick={handleSave}>Save</button>
</div>
);
};
解决方案
改进关注点的分离,我想你会更喜欢它。
- 在 中定义所有复选框事件处理程序
Filter
。 Filter
仅与Main
通过状态通信。- 不要强制
Main
评估 UI 组件以设置状态。 - 根据需要定义要使用的
Main
状态Filter
以避免上述情况。
- 不要强制
Filter
将构建复选框。Cancel
和Save
按钮对我来说似乎是Filter
关卡功能。- 一个
FilterMenu
组件现在看起来毫无意义,因为它什么都不做。Filter
也许在更大的架构中它是有用的,但你总是可以在需要时重新考虑它 Filter
组件是代码中将动作与状态分开的接缝。- 状态并没有被不必要地进一步推低。
- 实际功能不会不必要地进一步提升。
Main
和之间的耦合Filter
减少了。Filter
具有更大的重用潜力。
推荐阅读
- javascript - NodeJS:“未定义不是有效的 uri 或选项对象”与请求
- html - CSS类嵌套不起作用
- ethereum - 来自 eth.coinbase 的 eth.sendTransaction 进行多次交易并减少 eth.coinbase 余额
- python - 根据来自另一个 Dataframe for 循环的条件创建一个新的 Dataframe
- php - Angular 6 的代码点火器
- c++ - 获得利润和类型
- node.js - 如何配置 Node.js 服务器来提供 SVG 文件?
- google-cloud-build - Google Cloud Build - 是否支持多分支管道?
- scala - 无法在线安装 sbt(按照官方指南)
- c# - 如何公开具有动态数据类型的泛型方法?