Graphql提供useQuery挂钩来获取数据。每当组件重新渲染时,它将被调用。
//mocking useQuery hook of graphql, which updates the data variable
const data = useQuery(false);
我正在使用 useEffect 挂钩来控制应调用“ useQuery”的次数。
我想做的是每当我从useQuery接收数据时,我想对数据执行一些操作并将其设置为另一个状态变量“ stateOfValue ”,这是一个嵌套的对象数据。因此,这必须在useEffect挂钩内完成。
因此,我需要添加我的 stateOfValue 和“ 数据”(具有我的API数据)变量作为对useEffect挂钩的依赖项。
const [stateOfValue, setStateOfValue] = useState({
name: "jack",
options: []
});
const someOperation = (currentState) => {
return {
...currentState,
options: [1, 2, 3]
};
}
useEffect(() => {
if (data) {
let newValue = someOperation(stateOfValue);
setStateOfValue(newValue);
}
}, [data, stateOfValue]);
基本上,我将所有在useEffect中使用的变量添加为依赖项,因为这是进行according to Dan Abramov.的正确方法
现在,根据反应,状态更新必须在没有任何变化的情况下完成,因为每次我需要更新状态时,我都会创建一个新对象。但是通过设置一个新的状态变量对象,我的组件将被重新渲染,从而导致无限的渲染。
如何以将所有变量都传递到我的useEffect依赖项数组中并使它仅执行一次useEffect的方式来实现它。
请注意:,如果我不将 stateOfValue 变量添加到依赖项中,它将起作用,但这只是在做出反应。
答案 0 :(得分:2)
我认为你误会了
您想在依赖项数组中使用的是[data, setStateOfValue]
而不是[data, stateOfValue]
。因为您在setStateOfValue
内使用stateOfValue
而不是useEffect
合适的是:
const [stateOfValue, setStateOfValue] = useState({
name: "jack",
options: []
});
const someOperation = useCallback((prevValue) => {
return {
...prevValue,
options: [1, 2, 3]
};
},[])
useEffect(() => {
if (data) {
setStateOfValue(prevValue => {
let newValue = someOperation(prevValue);
return newValue
});
}
}, [data, setStateOfValue,someOperation]);
答案 1 :(得分:2)
如果要设置效果状态,可以执行以下操作:
const data = useQuery(query);
const [stateOfValue, setStateOfValue] = useState({});
const someOperation = useCallback(
() =>
setStateOfValue((current) => ({ ...current, data })),
[data]
);
useEffect(() => someOperation(), [someOperation]);
每次数据更改功能,都会重新创建SomeOperation功能,并使效果运行。有时会加载数据或出现错误,并且不会再次创建数据,从而导致无法再次创建someOperation且效果不会再次运行。
答案 2 :(得分:1)
首先,我想问您是否需要将stateOfValue
存储为状态。如果没有(例如,它将不会被其他任何东西编辑),则可能会使用useMemo
钩子
const myComputedValue = useMemo(() => someOperation(data), [data]);
现在myComputedValue
将是someOperation
的结果,但仅在数据更改时才会重新运行
如果有必要将其存储为状态,则可以使用onCompleted
中的useQuery
选项
const data = useQuery(query, {
onCompleted: response => {
let newValue = someOperation();
setStateOfValue(newValue);
}
)