React Hook useEffect 缺少依赖项:'dispatch' [英] React Hook useEffect has a missing dependency: 'dispatch'
问题描述
这是我第一次使用 react js,我试图在离开此视图时删除警报,因为我不想在另一个视图上显示它,但如果没有错误,我想保持成功当我要重定向到另一个视图时提醒显示它
但我在谷歌浏览器上穿这个第 97:6 行:React Hook useEffect 缺少依赖项:'dispatch'.要么包括它要么删除依赖数组 react-hooks/exhaustive-deps
如果我确实包含 dispatch 我会无限循环
const [state, dispatch] = useUserStore();useEffect(() => {让令牌 = params.params.token;检查令牌(令牌,调度);}, [params.params.token]);useEffect(() => {返回 () =>{如果(state.alert.msg ===错误"){派遣({类型:REMOVE_ALERT});}};}, [state.alert.msg]);//来自api的响应如果(!token_valide || token_valide_message ===完成"){return <Redirect to="/login"/>;}
这是 useUserStore
const globalReducers = useCombinedReducers({警报:useReducer(alertReducer,alertInitState),身份验证:useReducer(authReducer,authInitState),注册:useReducer(registerReducer, registerInitState),令牌:useReducer(passeditReducer,tokenvalidationInitState)});返回 (<appStore.Provider value={globalReducers}>{children}</appStore.Provider>);};export const useUserStore = () =>使用上下文(应用商店);
dispatch
来自自定义 hook
,因此它没有稳定的签名,因此会在每个渲染(引用相等).通过将处理程序包装在 useCallback
钩子
const [foo, dispatch] = myCustomHook()const stableDispatch = useCallback(dispatch, [])//假设不需要改变useEffect(() =>{稳定调度(富)},[stableDispatch])
useCallback
和 useMemo
是辅助钩子,主要目的是添加额外的依赖性检查层以确保同步.通常你想使用 useCallback
来确保对 prop
的稳定签名,你知道如何改变而 React 不会.
例如通过props
传递的function
(引用类型)
const 组件 = ({ setParentState }) =>{useEffect(() => setParentState('mounted'), [])}
假设你有一个子组件,在安装时必须在父组件中设置一些状态(不常见),上面的代码将在 useEffect
中生成未声明依赖项的警告,所以让我们声明 setParentState
作为要由 React 检查的依赖项
const 组件 = ({ setParentState }) =>{useEffect(() => setParentState('mounted'), [setParentState])}
现在这个效果在每次渲染上运行,不仅在安装时,而且在每次更新时.发生这种情况是因为 setParentState
是一个 function
,每次调用 Component
函数时都会重新创建它.你知道 setParentState
不会超时改变它的签名,所以告诉 React 是安全的.通过将原始助手包装在 useCallback
中,您就是在这样做(添加另一个依赖项检查层).
const 组件 = ({ setParentState }) =>{const stableSetter = useCallback(() => setParentState(), [])useEffect(() => setParentState('mounted'), [stableSetter])}
你去吧.现在 React
知道 stableSetter
不会在生命周期内改变它的签名,因此效果不需要不必要地运行.
附带说明 useCallback
它也像 useMemo
一样用于优化昂贵的函数调用(记忆).
useCallback
的两个主要目的是
优化依赖引用相等的子组件,防止不必要的呈现.
This is my first time working with react js , im trying to remove the alert when leaving this view cause i don't want to show it on the other view but in case that there is no error i want to keep the success alert to show it when i'm gonna redirect to the other view
but im getting this wearning on google chrome
Line 97:6: React Hook useEffect has a missing dependency: 'dispatch'. Either include it or remove the dependency array react-hooks/exhaustive-deps
if i did include dispatch i get infinite loop
const [state, dispatch] = useUserStore(); useEffect(() => { let token = params.params.token; checktoken(token, dispatch); }, [params.params.token]); useEffect(() => { return () => { if (state.alert.msg === "Error") { dispatch({ type: REMOVE_ALERT }); } }; }, [state.alert.msg]); //response from the api if (!token_valide || token_valide_message === "done") { return <Redirect to="/login" />; }
this is useUserStore
const globalReducers = useCombinedReducers({ alert: useReducer(alertReducer, alertInitState), auth: useReducer(authReducer, authInitState), register: useReducer(registerReducer, registerInitState), token: useReducer(passeditReducer, tokenvalidationInitState) }); return ( <appStore.Provider value={globalReducers}>{children}</appStore.Provider> ); }; export const useUserStore = () => useContext(appStore);
解决方案dispatch
comes from a customhook
so it doesn't have an stable signature therefore will change on each render (reference equality). Add an aditional layer of dependencies by wrapping the handler inside anuseCallback
hookconst [foo, dispatch] = myCustomHook() const stableDispatch = useCallback(dispatch, []) //assuming that it doesn't need to change useEffect(() =>{ stableDispatch(foo) },[stableDispatch])
useCallback
anduseMemo
are helper hooks with the main purpose off adding an extra layer of dependency check to ensure synchronicity. Usually you want to work withuseCallback
to ensure a stable signature to aprop
that you know how will change and React doesn't.A
function
(reference type) passed viaprops
for exampleconst Component = ({ setParentState }) =>{ useEffect(() => setParentState('mounted'), []) }
Lets assume you have a child component which uppon mounting must set some state in the parent (not usual), the above code will generate a warning of undeclared dependency in
useEffect
, so let's declaresetParentState
as a dependency to be checked by Reactconst Component = ({ setParentState }) =>{ useEffect(() => setParentState('mounted'), [setParentState]) }
Now this effect runs on each render, not only on mounting, but on each update. This happens because
setParentState
is afunction
which is recreated every time the functionComponent
gets called. You know thatsetParentState
won't change it's signature overtime so it's safe to tell React that. By wrapping the original helper inside anuseCallback
you're doing exactly that (adding another dependency check layer).const Component = ({ setParentState }) =>{ const stableSetter = useCallback(() => setParentState(), []) useEffect(() => setParentState('mounted'), [stableSetter]) }
There you go. Now
React
knows thatstableSetter
won't change it's signature inside the lifecycle therefore the effect do not need too run unecessarily.On a side note
useCallback
it's also used likeuseMemo
, to optmize expensive function calls (memoization).The two mai/n purposes of
useCallback
areOptimize child components that rely on reference equality to prevent unnecessary renders. Font
Memoize expensive calculations
UPDATE 09/11/2020
This solution is no needed on
es-lint-plugin-react-hooks@4.1.0
and above.Now
useMemo
anduseCallback
can safely receive referential types as dependencies.#19590function MyComponent() { const foo = ['a', 'b', 'c']; // <== This array is reconstructed each render const normalizedFoo = useMemo(() => foo.map(expensiveMapper), [foo]); return <OtherComponent foo={normalizedFoo} /> }
Here is another example of how to safely stabilize(normalize) a callback
const Parent = () => { const [message, setMessage] = useState('Greetings!') return ( <h3> { message } </h3> <Child setter={setMessage} /> ) } const Child = ({ setter }) => { const stableSetter = useCallback(args => { console.log('Only firing on mount!') return setter(args) }, [setter]) useEffect(() => { stableSetter('Greetings from child\'s mount cycle') }, [stableSetter]) //now shut up eslint const [count, setCount] = useState(0) const add = () => setCount(c => c + 1) return ( <button onClick={add}> Rerender {count} </button> ) }
Now referential types with stable signature such as those provenients from
useState
oruseDispatch
can safely be used inside an effect without triggeringexhaustive-deps
even when coming fromprops
这篇关于React Hook useEffect 缺少依赖项:'dispatch'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!