React中基于props设置更新子组件状态且避免无限循环的方案
问题根源
你写的顶层if判断每次组件渲染都会执行,一旦条件满足就会调用setActiveClass触发子组件重渲染,重渲染又会再次执行这个判断、再次调用setState,最终形成无限循环。
方案1:直接计算派生状态(最优解)
你场景下的activeClass完全由传入的props决定,没有独立的状态逻辑,完全不需要额外声明useState存储,直接在渲染时计算即可,代码最简洁也不会有性能问题:
function Button(props) { const Icon = Icons[props.icon]; // 直接计算active类名,不需要存state const activeClass = props.active == props.index ? "active" : ""; function toggleView(e) { e.preventDefault(); props.handler(props.index); } return( <button className={activeClass} data-index={props.index} onClick={toggleView}> <Icon /> </button> ) }
方案2:用useEffect监听props变化(适用于必须存state的特殊场景)
如果你的实际业务逻辑确实需要把这个值存在子组件state中,就把同步逻辑放到useEffect中,只有当依赖的props变化时才会执行状态更新,不会触发无限循环:
import { useEffect } from 'react'; function Button(props) { const Icon = Icons[props.icon]; const [activeClass, setActiveClass] = useState(""); // 仅当active或index props变化时同步状态 useEffect(() => { setActiveClass(props.active == props.index ? "active" : ""); }, [props.active, props.index]); // 第二个参数是依赖数组,只有数组内的变量发生变化时,副作用函数才会执行 function toggleView(e) { e.preventDefault(); props.handler(props.index); } return( <button className={activeClass} data-index={props.index} onClick={toggleView}> <Icon /> </button> ) }
优先选择方案1,没有冗余状态和额外副作用,维护成本更低。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

