我在这里有点困惑。根据这个 SO 问题以及这个问题,我应该能够在调用useQuery
钩子以填充状态后调用useEffect
钩子,我正在通过useReducer
进行操作。例如,像这样的东西(假设foo
、bar
和baz
是向 GraphQL 服务器的单个请求中的命名查询(:
const MyComponent = ( props ) => {
const [ state, dispatch ] = useReducer( reducer, initialState )
const query = someCondition ? query1 : query2
const variables = { variables: someCondition ? query1Vars : query2Vars }
const { loading, error, data } = useQuery( query, variables )
useEffect(function() {
dispatch({
type: types.INIT,
payload: {
foo: data.foo,
bar: data.bar,
baz: data.baz
}
})
}, [data])
return (
<div>
{
(() => {
if ( loading ) return <Loading />
if ( error ) return <Error />
return (
// components that depend on data
)
})()
}
</div>
)
}
由于我无法确定的原因,当我在useEffect
中引用它时,data
undefined
。我已经检查了我的网络响应,对我的 GraphQL 端点的调用确实在返回数据。(本质上,在另一个关于useQuery的SO问题中描述了什么。
除了条件查询/变量赋值外,此代码还用于我们的其他一些组件,并且工作正常,所以我不知道为什么它在我的情况下不起作用。
我不确定这里发生了什么,因为我已经确保没有有条件地调用钩子,这违反了钩子的规则;我所做的只是在通过 Apollo 客户端发送查询之前有条件地分配变量值。(我也尝试了useQuery
选项的onCompleted
属性,没有useEffect
钩子,但无济于事;data
仍然undefined
。
除非我不完全了解您的问题,否则这看起来像是预期的行为。
useEffect
将在挂载时触发,然后在data
更改时触发,data
仅在 API 调用完成后才会更改。初始useEffect
调用将在useQuery
从服务器获得响应之前发生,因此您不能在内部假设useEffect
将设置data
。
如果您只想在data
在那里时调度,那么您应该保护呼叫,例如
useEffect(() => {
if (data) {
dispatch({
type: types.INIT,
payload: {
foo: data.foo,
bar: data.bar,
baz: data.baz
}
});
}
}, [data]);