调用 useEffect 挂钩时未定义 useQuery 数据?

useQuery data undefined when calling useEffect hook?

我在这里有点困惑。根据 and also ,我应该能够在调用 useQuery 挂钩填充状态后调用 useEffect 挂钩,这是我通过 useReducer 所做的。例如,类似这样的事情(假设 foobarbaz 是对 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 中引用它时,dataundefined。我检查了我的网络响应,对我的 GraphQL 端点的调用确实返回了数据。 (本质上,this other SO question about useQuery 中描述的内容。)

除了有条件的 query/variable 赋值外,这段代码用于我们的其他一些组件并且工作正常,所以我不知道为什么它在我的情况下不起作用。

我不确定这里发生了什么,因为我已经确定没有有条件地调用任何钩子,这违反了钩子的规则;我所做的只是在通过 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]);