reactjs - useState React 钩子总是返回初始值
问题描述
locationHistory 在以下代码中始终是一个空数组:
export function LocationHistoryProvider({ history, children }) {
const [locationHistory, setLocationHistory] = useState([])
useEffect(() => history.listen((location, action) => {
console.log('old state:', locationHistory)
const newLocationHistory = locationHistory ? [...locationHistory, location.pathname] : [location.pathname]
setLocationHistory(newLocationHistory)
}), [history])
return <LocationHistoryContext.Provider value={locationHistory}>{children}</LocationHistoryContext.Provider>
}
console.log
总是记录[]
。我尝试在常规反应类中做完全相同的事情并且它工作正常,这让我认为我使用错误的钩子。
任何建议将不胜感激。
更新:删除useEffect
( [history]
) 的第二个参数修复它。但为什么?目的是不需要在每次重新渲染时重新运行此效果。因为它不应该是。我认为这就是效果器的工作方式。
添加一个空数组也会破坏它。它似乎[locationHistory]
必须作为第二个参数添加,以useEffect
阻止它中断(或根本没有第二个参数)。但我很困惑为什么这会阻止它破裂?history.listen
应在位置更改时运行。为什么useEffect
每次locationHistory
更改都需要重新运行,以避免上述问题?
PS在这里玩一下:https ://codesandbox.io/s/react-router-ur4d3?fontsize= 14(感谢lissitz在那里做了大部分的腿部工作)
解决方案
history
您正在为该对象设置一个侦听器,对吗?
假设您的history
对象在多个渲染中保持相同(相同的对象引用),您应该这样做:
- 在第一次渲染后设置监听器(即:安装后)
- 卸载后删除监听器
为此,您可以这样做:
useEffect(()=>{
history.listen(()=>{//DO WHATEVER});
return () => history.unsubscribe(); // PSEUDO CODE. YOU CAN RETURN A FUNCTION TO CANCEL YOUR LISTENER
},[]); // THIS EMPTY ARRAY MAKES SURE YOUR EFFECT WILL ONLY RUN AFTER 1ST RENDER
但是,如果您的history
对象在每次渲染时都会发生变化,您需要:
- 取消最后一个监听器(来自上一个渲染)和
- 每次你的历史对象改变时设置一个新的监听器。
useEffect(()=>{
history.listen(()=>{//DO SOMETHING});
return () => history.unsubscribe(); // PSEUDO CODE. IN THIS CASE, YOU SHOULD RETURN A FUNCTION TO CANCEL YOUR LISTENER
},[history]); // THIS ARRAY MAKES SURE YOUR EFFECT WILL RUN AFTER EVERY RENDER WITH A DIFFERENT `history` OBJECT
注意:setState
函数保证在每个渲染中都是相同的实例。所以他们不需要在依赖数组中。
但是,如果您想访问useEffect
. 您不应该像使用 the 那样直接使用它locationHistory
(可以,但如果这样做,您需要将它添加到依赖项数组中,并且您的效果将在每次更改时运行)。为了避免直接访问它并将其添加到依赖数组中,您可以这样做,使用方法的函数形式setState
。
setLocationHistory((prevState) => {
if (prevState.length > 0) {
// DO WHATEVER
}
return SOMETHING; // I.E.: SOMETHING WILL BE YOUR NEW STATE
});
推荐阅读
- r - 从“|”读取数据时获取不需要的撇号字符 (管道)R中的分隔文本文件
- google-chrome - 是否可以添加一个在出现控制台错误时执行某些操作的 EventListener?
- r - 当所有变量都丢失时,在 SparklyR 中创建一个指示变量
- python-3.x - 我正在尝试制作一个删除字符串中元音的函数
- azure-api-management - 当调用包含订阅密钥时如何消除跟踪(防止 Ocp-Apim-Trace)?
- angular - 带有登录表单的标头和令牌的 Angular、http 请求
- python - 将许多 argparse 条件论证转换为更 Pythonic 的解决方案
- google-cloud-composer - Pubsub 中的时间触发器 + 多个事件
- swift - 迅速。如何删除字符串开头和结尾的字符?
- java - 如何交错(合并)两个 Java 8 流?