第一种情况:
_假设我有一个处于redux状态或父状态的道具。
_我不希望在此道具发生更改时触发useEffect,
_但是我确实需要在useEffect中使用道具。
_React警告我将prop添加到依赖项数组,但是如果这样做,则useEffect将再次触发。
第二种情况:
_我正在useEffect中使用函数,
_但是该功能在其他地方也需要。
_不想重复功能代码。
_React希望我将函数添加到依赖项数组中,但是我不希望每次函数引用发生更改时都触发useEffect。
答案 0 :(得分:2)
在使用useEffect时,您应该考虑闭包。如果在useEffect中使用了任何props或局部变量,则建议将其包含在依赖项数组中,否则由于关闭,您将使用过时的数据。
在这里,我介绍一个用例。在ComponentUsingRef内部,我们使用ref作为容器。您可以在https://reactjs.org/docs/hooks-reference.html#useref
上找到更多有关它的信息。这种方法的优点是您不必在其中记住fn 您的父组件。您将始终使用的最新值 函数,在给定的情况下,它甚至不会引起useEffect的触发,因为它不会取决于您的依赖项
const Component=({fn})=>{
useEffect(()=>{
fn()
},[fn])
.....
.....
return <SomeComponent {...newProps}/>
}
const ComponentUsingRef=({fn}){
const fnRef = useRef(fn)
fnRef.current = fn // so that our ref container contains the latest value
useEffect(()=>{
fn.current()
},[ ])
.....
.....
return <SomeComponent {...newProps}/>
}
如果要使用抽象,则应在custom hook
答案 1 :(得分:1)
如果唯一的问题是警告,那么请不要担心,如果效果是唯一使用的道具,则可以简单地禁用效果规则,并从依赖项数组中忽略该道具。对于具有多个依赖项的效果,可以使用useRef
来存储道具的最新值而不触发效果,如下所示:
const Comp = ({someProp, ...props}) => {
const myProp = useRef(someProp);
myProp.current = someProp;
// this effect won't fire when someProp is changed
React.useEffect(() => {
doSomething(myProp.current, props.a, props.b);
}, [props.a, props.b, myProp]);
}
对于第二种情况,我可能会将该函数放在单独的文件中,并将其导入将要使用的组件中,但是,对于第二种情况,您可以使用相同的模式。
答案 2 :(得分:0)
要忽略反应给您的警告,可以通过在// eslint-disable-next-line react-hooks/exhaustive-deps
代码中添加useEffect
来禁用警告。您可以在React文档的Rules of Hooks部分中阅读有关此内容的更多信息。这些规则包含在eslint-plugin-react-hooks
package中。
要防止在每次函数引用更改时都触发useEffect,可以使用useCallback
。 useCallback
钩子将存储对函数的引用,而不是函数本身。仅当更新函数依赖项之一时,函数参考才会更新。如果您不希望函数引用永远进行更新,则可以使用与useEffect
挂钩的依赖项数组相同的方式将依赖项数组留空。
Here is a working example of both:
import React, { useState, useEffect, useCallback } from "react";
import "./styles.css";
export default function App() {
const [value, setValue] = useState(0);
const wrappedFunction = useCallback(
(caller) => {
const newValue = value + 1;
setValue(newValue);
console.log(`Firing function from ${caller}: ${newValue}`);
},
[value]
);
useEffect(() => {
console.log(`Logging from useEffect: ${value}`);
wrappedFunction("useEffect");
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div>{value}</div>
<button onClick={() => wrappedFunction("button click")}>
Fire function
</button>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
答案 3 :(得分:0)
请参阅此链接以获取第一个问题Sandbox
在这里,我们仅使用状态变量来保存初始值,无论它是来自Parent还是Store,所以即使在Parent或store中更改值,子级仍将使用旧值,直到除非它使用useEffect更新它。
父母
export default function App() {
const [state, setState] = useState("monika");
return (
<div className="App">
<h1>My Name is {state}</h1>
<button
onClick={() => {
setState("Rohan");
}}
>
change name
</button>
<First username={state} />
</div>
);
}
孩子
export default function First({ username }) {
const [name, setName] = useState(username);
return (
<div>
<h1>My Name is {name}</h1>
</div>
);
}