React带按钮搜索栏如何从props更新状态并移除isInitialized标识
优化方案
核心问题分析
你当前需要isInitialized标识的根本原因是存在冗余状态设计:你把Redux store中存储的全量caseMonitors又同步了一份到组件state中,额外引入了props到state的同步逻辑,才需要初始化标识来控制同步时机。
最优解决方案:移除组件内冗余的列表状态
全量列表直接复用Redux传入的props,组件state只保留搜索关键词和「是否点击过搜索按钮」的标识,完全不需要isInitialized,同时满足点击按钮才展示列表的需求。
修改后的主组件代码如下:
class MonitorManagement extends React.PureComponent { constructor(props, context) { super(props, context) this.state = { searchString: '', isSearchTriggered: false // 控制列表是否展示,默认不展示 } } componentDidMount() { // 组件挂载时只请求一次全量列表,无需重复调用 this.props.handlers.onGetCaseMonitors() } componentWillUnmount() { this.props.handlers.onClearCaseMonitors() } onSearchHandler = () => { // 点击搜索按钮仅修改展示标识,不需要修改Redux存储的全量列表 this.setState({ isSearchTriggered: true }) } onSearchUpdate = searchString => this.setState({ searchString }) renderSearch = () => { const { searchString } = this.state const { caseMonitors } = this.props return ( <Search caseMonitors={caseMonitors} value={searchString} handlers={{ onSearchUpdate: this.onSearchUpdate, onSearchHandler: this.onSearchHandler }} /> ) } renderList = () => { const { isSearchTriggered, searchString } = this.state const { caseMonitors } = this.props // 未点击搜索按钮时不展示列表 if (!isSearchTriggered) return null // 全量列表还未从Redux返回时展示加载态 if (!caseMonitors) return <Spinner /> // 过滤逻辑放在渲染时执行,不需要存到state const filteredMonitors = searchString ? caseMonitors.filter(({ name }) => name.toLowerCase().includes(searchString.toLowerCase()) ) : caseMonitors return <List caseMonitors={filteredMonitors} /> } render() { return ( <div> {this.renderSearch()} {this.renderList()} </div> ) } }
这个方案的优势:
- 完全移除了
isInitialized标识,没有props到state的同步逻辑,减少维护成本 - 符合「点击按钮才展示列表」的产品需求,未点击时不会渲染列表相关节点
- 避免了每次搜索重复请求接口、清空Redux状态的冗余操作,性能更优
- 全量列表唯一数据源是Redux store,不会出现state和props数据不一致的问题
备选方案:如果必须将全量列表存储在组件state
如果业务场景要求必须在组件内存储全量列表,可以用getDerivedStateFromProps生命周期替代原来的componentDidUpdate同步逻辑,同样可以移除isInitialized:
static getDerivedStateFromProps(nextProps, prevState) { // 仅当Redux返回了列表数据、且组件state还未存储全量列表时同步 if (nextProps.caseMonitors && !prevState.fullCaseMonitors) { return { fullCaseMonitors: nextProps.caseMonitors } } return null }
注意组件state需要单独存fullCaseMonitors作为全量数据源,不要直接覆盖用来渲染过滤后列表的字段,避免每次搜索都要重新同步全量数据。
内容的提问来源于stack exchange,提问作者karo-s
相关产品推荐
相关产品推荐

