React类组件实现的Provider Context中如何正确更新state
根因分析
你遇到的警告是因为在组件渲染流程中直接触发了状态更新:你在Index组件的顶层作用域直接调用setItemsArray,这段代码会在组件每次渲染时同步执行,而setItemsArray内部触发了DragAndDropProvider的setState,导致Provider重渲染,进而触发所有消费该Context的子组件(包括Index组件)再次渲染,形成「渲染→更新状态→渲染」的循环,React检测到这个风险后抛出了对应警告。
修复方案
1. 调整Index组件的状态更新时机
把setItemsArray的调用包裹在useEffect钩子中,仅当documents发生变化时才触发更新,避免每次渲染都执行状态变更逻辑:
import { useEffect } from 'react'; // 原有逻辑保留 const documents = UseGetDocuments(); const { state, setItemsArray } = useContext(DragAndDropContext); // 新增useEffect包裹更新逻辑 useEffect(() => { // 可选:如果documents是异步获取的,可加判断避免空值覆盖 if (documents?.length) { setItemsArray(documents); } }, [documents, setItemsArray]);
2. 可选优化:避免DragAndDropProvider不必要的重渲染
你当前的实现中,每次Provider渲染都会生成全新的Context value对象,哪怕items没有变化,也会触发所有消费该Context的组件强制重渲染,可按如下方式调整Provider实现:
export class DragAndDropProvider extends Component<any, any> { constructor(props: any) { super(props); // 提前绑定方法引用,避免重复创建 this.an_independent_function = this.an_independent_function.bind(this); this.moveItem = this.moveItem.bind(this); this.setItems = this.setItems.bind(this); // 将Context value存入state,仅在需要时更新 this.state = { items: [], moveItem: this.moveItem, setItems: this.setItems, contextValue: { state: this.state, setItemsArray: this.an_independent_function } }; } an_independent_function(documents: any) { console.log(documents); this.setState(prevState => ({ items: documents, // 仅更新contextValue中的state部分,保留其他引用不变 contextValue: { ...prevState.contextValue, state: { ...prevState.contextValue.state, items: documents } } })) } render() { return ( <DragAndDropContext.Provider value={this.state.contextValue}> {this.props.children} </DragAndDropContext.Provider> ); } }
内容的提问来源于stack exchange,提问作者Janio Carvalho
相关产品推荐
相关产品推荐

