React中如何在存储的函数中便捷使用useState状态值?
我有一个React组件,使用useState存储待展示的项数组,以此实现列表更新与重渲染。我尝试创建可存储并传递给其他组件的排序函数,用于更新列表并展示结果,但存储后的函数仅能获取useState的初始值。
示例代码如下:
export default function MyWindow ({someAccessor}) { const [objectList, setObjectList] = useState([]) const sortObjects = () => { let newList = [...objectList] newList.sort(someSortFunction) setObjectList(newList) } const createAndSortObjects = () => { let newList = [1, 2, 3, etc.] newList.sort(someSortFunction) setObjectList(newList) } useEffect(() => { populateObjectListFunction() //Line 1 someAccessor.passFunction(sortObjects) //Line 2 someAccessor.passFunction(createAndSortObjects ) //Line 3 }, []) return ( <div> {objectList.mapTo(someComponentMap)} </div> ) }
当accessor调用Line3的createAndSortObjects函数时,它能创建新数组、排序并更新objectList变量;但调用Line2的sortObjects时,仅会使用objectList的初始值[],覆盖Line3填充的数组。
我该如何便捷解决此问题,让Line2的函数能更新现有列表?我知道可以用useRef访问.current值,但这需要维护两个变量;又不能放弃useState,否则组件无法在列表变化时重渲染,该怎么做?
核心问题是闭包捕获旧状态:sortObjects在组件挂载时被传递给someAccessor,此时它捕获的是objectList的初始值[],后续状态更新后,这个函数里的objectList还是旧值。
最便捷的解决方式是使用setObjectList的函数式更新,这种方式会自动传入当前最新的状态值,不需要依赖闭包中的objectList:
修改sortObjects函数:
const sortObjects = () => { setObjectList(prevList => { let newList = [...prevList] newList.sort(someSortFunction) return newList }) }
这样不管sortObjects什么时候被调用,都会基于当前最新的objectList状态来排序,不会再出现使用初始值的问题。
另外,如果someSortFunction是外部传入或者可能变化的,记得把它加入useEffect的依赖数组,确保传递给someAccessor的函数能捕获到最新的排序逻辑:
useEffect(() => { populateObjectListFunction() someAccessor.passFunction(sortObjects) someAccessor.passFunction(createAndSortObjects ) }, [someSortFunction])
这种方式不需要额外维护useRef,完全基于useState的原生能力解决问题,同时保留组件状态更新时的重渲染特性。
内容的提问来源于stack exchange,提问作者William Convertino

