React自定义Hook报错:不是函数或返回值不可迭代
问题根源
你犯了一个核心错误:Redux的connect是高阶组件,只能用来包裹React组件,不能用来包装自定义Hook。
你用connect包装useLocalStorageHandler后,导出的已经不是一个Hook函数,而是一个React组件。当你在Submission里像调用Hook一样执行useLocalStorageHandler()时,本质上是在尝试调用一个组件,这就会触发not a function的错误,更不可能返回[state, setState]这样的可迭代数组。
另外看你的代码,useLocalStorageHandler里接收的setTaskSubmissions参数从头到尾没被使用,这部分Redux关联完全是多余的。
修复方案
方案1:移除多余的Redux connect(推荐,因为你没用到Redux)
直接删除所有Redux相关代码,让useLocalStorageHandler回归纯Hook:
import React from 'react'; import { useState, useRef, useEffect } from 'react'; function useLocalStorageHandler(key, defaultValue = '') { const [state, setState] = useState(() => { // 从localStorage读取,处理初始值 const storedValue = window.localStorage.getItem(key); return storedValue !== null ? storedValue : defaultValue; }); const prevKeyRef = useRef(key); useEffect(() => { const prevKey = prevKeyRef.current; if (prevKey !== key) { window.localStorage.removeItem(prevKey); } prevKeyRef.current = key; window.localStorage.setItem(key, state); }, [key, state]); return [state, setState]; } export default useLocalStorageHandler;
然后修改Submission组件的导入语句(因为现在是默认导出):
// 把命名导入改成默认导入 import useLocalStorageHandler from '../../../hooks/useLocalStorageHandler';
方案2:如果确实需要在Hook中使用Redux(假设后续会用到)
不要用connect包裹Hook,而是在Hook内部使用Redux的useDispatch和useSelector Hook:
import React from 'react'; import { useState, useRef, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { setTaskSubmissions } from '../redux/actions/main'; function useLocalStorageHandler(key, defaultValue = '') { const dispatch = useDispatch(); const taskSubmissions = useSelector(state => state.main.taskSubmissions); const [state, setState] = useState(() => { const storedValue = window.localStorage.getItem(key); return storedValue !== null ? storedValue : defaultValue; }); const prevKeyRef = useRef(key); useEffect(() => { const prevKey = prevKeyRef.current; if (prevKey !== key) { window.localStorage.removeItem(prevKey); } prevKeyRef.current = key; window.localStorage.setItem(key, state); // 示例:如果需要用dispatch更新Redux状态 // dispatch(setTaskSubmissions(...)) }, [key, state, dispatch]); return [state, setState]; } export default useLocalStorageHandler;
同样,Submission组件的导入要改成默认导入,调用方式不变。
额外注意点
- React Hook必须遵循Hook规则:只能在函数组件或其他自定义Hook的顶层调用,不能在条件、循环里调用。你的
Submission组件调用方式是符合规则的,修复后就能正常运行。 - 初始值读取逻辑可以优化:原代码里
window.localStorage.getItem(key) || defaultValue有问题,如果localStorage里存的是'false'、'0'这类 falsy 值,会被错误替换成defaultValue。所以改成判断storedValue !== null更严谨。
内容的提问来源于stack exchange,提问作者Manikandan
相关产品推荐
相关产品推荐

