Данные useQuery не определены при вызове ловушки useEffect? - PullRequest
0 голосов
/ 31 января 2020

Я немного сбит с толку. В соответствии с этим вопросом SO , а также этим вопросом , я должен иметь возможность вызвать хук useEffect после вызова хука useQuery для заполнения состояния, которое я делаю через 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>
  )
}

По причинам, которые я не могу определить, data равно undefined, когда я ссылаюсь на него внутри useEffect. Я проверил свои сетевые ответы, и вызов моей конечной точки GraphQL действительно возвращает данные. (По сути, то, что описано в этом другом SO-вопросе об useQuery .)

За исключением условного запроса / назначения переменной, этот код используется для некоторых других наших компонентов и работает нормально. , поэтому я понятия не имею, почему это не работает в моем случае.

Я не уверен, что здесь происходит, так как я убедился, что никакие хуки не вызываются условно, в нарушение правил крюки; все, что я делаю, это условно присваиваю значения переменных до отправки запроса через клиент Apollo. (Я также пробовал свойство onCompleted параметров useQuery без хука useEffect, но безрезультатно; data по-прежнему undefined.)

1 Ответ

1 голос
/ 31 января 2020

Если я не до конца понимаю вашу проблему, это похоже на ожидаемое поведение.

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]);
...