我有一个React组件,它使用useEffect
钩子来获取数据,如下所示:
const cache = {key: "data-fetched-using-key"}
function Config({key, options}) {
const [data, setData] = useState();
useEffect(() => {
const fetchedData; // fetch data using key and options
setData(fetchedData);
cache[key] = fetchedData;
}, [key, options])
return <p>{data}</p>;
}
每次key
或options
更改时,该钩子都会运行。但是,我也在本地缓存数据,并且只希望在key
和options
都更改时才运行效果(由于每个键/选项的组合,数据将始终相同)。 / p>
是否有一种干净的方法可以依靠React Hooks来依靠key
和options
的组合,而不是key
或options
呢?
答案 0 :(得分:3)
您可以使用useRef()
创建这种逻辑。考虑以下示例和沙箱:https://codesandbox.io/s/react-hooks-useeffect-with-multiple-reqs-6ece5
const App = () => {
const [name, setName] = useState();
const [age, setAge] = useState();
const previousValues = useRef({ name, age });
useEffect(() => {
if (
previousValues.current.name !== name &&
previousValues.current.age !== age
) {
//your logic here
console.log(name + " " + age);
console.log(previousValues.current);
//then update the previousValues to be the current values
previousValues.current = { name, age };
}
});
return (
<div>
<input
placeholder="name"
value={name}
onChange={e => setName(e.target.value)}
/>
<input
placeholder="age"
value={age}
onChange={e => setAge(e.target.value)}
/>
</div>
);
};
工作流程:
ref
对象,
在这种情况下,其为name
和age
。引用对象是previousValues
。useEffect
已定义,但我们不提供任何依赖关系。
相反,只要状态发生更改,我们就执行它
name
或age
。useEffect
中,我们有条件逻辑来检查
name
和age
的先前/初始值与
它们相应的状态值。如果他们那么好,我们执行
我们的逻辑(console.log)
。(previousValues)
更新为当前值(state)
。答案 1 :(得分:3)
为了在两个值都改变时运行效果,您需要利用先前的值并在键或选项中的任何一个改变时在挂钩中对其进行比较
为此,您可以编写一个usePrevious钩子,并比较本文中提到的旧状态和先前状态
How to compare oldValues and newValues on React Hooks useEffect?
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const cache = {key: "data-fetched-using-key"}
function Config({key, options}) {
const [data, setData] = useState();
const previous = usePrevious({key, options});
useEffect(() => {
if(previous.key !== key && previous.options !== options) {
const fetchedData; // fetch data using key and options
setData(fetchedData);
cache[key] = fetchedData;
}
}, [key, options])
return <p>{data}</p>;
}
答案 2 :(得分:0)
提供的所有解决方案都很好,但是存在一些更复杂的情况,例如,仅当依赖项A和B更改而它也依赖于C的值时,才应调用useEffect函数。
因此,我建议使用useEffects序列和中间状态为将来的逻辑提供更多空间。实施该方法可以解决以下问题:
const cache = {key: "data-fetched-using-key"}
function Config({key, options}) {
const [data, setData] = useState();
const [needsUpdate, setNeedsUpdate] = useState(()=>({key:false, option:false}));
useEffect(()=>{
setNeedsUpdate((needsUpdate)=>({...needsUpdate, key:true}));
},[key])
useEffect(()=>{
setNeedsUpdate((needsUpdate)=>({...needsUpdate, options:true}));
},[options])
useEffect(() => {
if (needsUpdate.key && needsUpdate.options){
const fetchedData; // fetch data using key and options
setData(fetchedData);
cache[key] = fetchedData;
setNeedsUpdate(()=>({key:false, option:false}));
}
}, [needsUpdate, key, options])
return <p>{data}</p>;
}
通过这种方式,我们几乎可以对useEffect依赖项应用任何逻辑,但是它也有缺点,那就是渲染周期更长。