React无限渲染困境:修改状态数组的取舍问题
React状态数组修改与无限渲染问题解决
一、解决无限渲染问题
你当前的B组件直接在函数体中调用setWords(arrayGen()),会导致每次组件渲染都触发状态更新,状态更新又引发重新渲染,形成无限循环。正确做法是仅在依赖项变化时更新状态,比如props.enteredTxt变化时才更新数组。
修改后的B组件代码:
B = (props) => { const [words, setWords] = useState([]); // 监听props.enteredTxt变化,仅当新值传入时更新数组 useEffect(() => { if (props.enteredTxt) { // 通过解构原数组创建新数组,添加新元素 setWords(prevWords => [...prevWords, props.enteredTxt]); } }, [props.enteredTxt]); // 依赖项:仅当enteredTxt变化时执行 return( <div> {words.join('')} </div> ); }
问题根源说明
- 直接在组件函数体调用
setWords:每次渲染都会触发状态更新,陷入渲染循环。 - 直接修改状态数组(
words.length=0、words.push):React状态是不可变的,直接修改原数组不会触发组件更新,还会导致状态不一致。
二、React清空数组的规范做法
React中状态不可直接修改,清空数组必须通过创建新数组的方式更新状态,常见规范做法如下:
直接设置为空数组
最简单直接的方式,给状态更新函数传入新的空数组:setWords([]);类组件场景(创建副本后清空)
类组件中可通过slice()创建原数组副本后清空,不过更简洁的方式还是直接设置空数组:// 类组件中推荐写法 this.setState({ data: [] }); // 冗余但可行的写法(不推荐) const newArray = this.state.data.slice(); newArray.length = 0; this.setState({ data: newArray });使用
filter返回空数组
适合需基于原数组条件清空的场景,始终返回空数组即可:setWords(prevWords => prevWords.filter(() => false));
核心原则
无论哪种方式,必须保证更新后的状态是新的引用,不能直接修改原状态数组。React通过对比状态引用变化判断是否重新渲染,直接修改原数组不会触发更新。
内容的提问来源于stack exchange,提问作者Touchstone
相关产品推荐
相关产品推荐

