【发布时间】:2020-05-17 09:36:42
【问题描述】:
我在这里有点困惑。根据this SO question 和this question,我应该能够在调用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 端点的调用确实在返回数据。 (基本上,this other SO question about useQuery 中描述的内容。)
除了条件查询/变量赋值之外,此代码用于我们的其他一些组件并且工作正常,所以我不知道为什么它在我的情况下不起作用。
我不确定这里发生了什么,因为我已经确保没有违反钩子规则的有条件地调用任何钩子;我所做的只是有条件地分配变量值之前通过 Apollo 客户端发送查询。 (我还尝试了useQuery 选项的onCompleted 属性,没有useEffect 钩子,但无济于事;data 仍然是undefined。)
【问题讨论】:
-
这对我来说似乎是预期的行为?
useEffect将始终在useQuery完成之前触发,我期望useEffect会触发两次,一次是在组件挂载时,第二次是在useQuery返回结果时。在我看来,当data尚未设置时,您没有考虑初始useEffect调用。 -
嗯,添加对
if ( data ) { ... }的检查似乎并不能解释useEffect钩子的初始触发。 github.com/trojanowski/react-apollo-hooks/issues/158 似乎建议您根本不需要使用useEffect,但我之前已经看到该代码有效。初始渲染应该如何处理? -
正确,你没有,因为
useQuery已经为你存储了状态 - 但是我不知道你的用例,只在你想要进入的地方关闭你提供的代码某种形式的减速器。 -
data正如@James 指出的那样,最初将是未定义的。如果遇到网络错误,它也可以无限期地未定义。也就是说,几乎没有理由这样做——useQuery已经为您管理状态。如果您需要进一步转换此状态,则只需将其作为组件内的常规变量即可。 -
感谢@DanielRearden,正如我在下面的评论中提到的,我用我的子组件更改了一些渲染,即使状态不支持它们,这些组件显然也在渲染。我确实为
useQuery使用了onCompleted回调,但是我看到了很多useQuery+useEffect的例子,我确信它应该像描述的那样工作,或者至少不会有问题。 :)
标签: reactjs graphql react-hooks react-apollo