Неверный вызов крюка. Хуки могут быть вызваны только внутри тела функционального компонента с помощью response-apollo - PullRequest
2 голосов
/ 17 октября 2019

Я получаю эту ошибку, пытаясь использовать response-apollo от публичного graphql api .

Недопустимый вызов ловушки. Хуки могут быть вызваны только внутри тела функционального компонента. Это может произойти по одной из следующих причин:

  1. У вас могут быть несовпадающие версии React и средства визуализации (например, React DOM)
  2. Возможно, вы нарушаете правила хуков
  3. Возможно, в одном приложении может быть несколько копий React

Я прочитал Реакция документации , и я уверен, что проблема в том,ни одна из этих трех причин.

Это простой проект, использующий create-react-app. Обе версии react и react-dom 16.10.2.

app.js:

import React, {useState} from 'react';
import { Query } from "react-apollo";
import { gql } from "apollo-boost";

const query = gql`
  {
    countries {
      name
      code
    }
  }
`;

function App() {
    const [country, setCountry] = useState('US');
    const onCountryChange = event => {
      setCountry(event.target.value);
    };

    return (
      <div className="App">
        <Query query={query}>
          {result => {
            if (result.loading) return <p>Loading...</p>;
            if (result.error) return <p>{result.error.message}</p>;
            return (
              <select value={country} onChange={onCountryChange}>
                {result.data.countries.map(country => (
                  <option key={country.code} value={country.code}>
                    {country.name}
                  </option>
                ))}
              </select>
            );
          }}
        </Query>
      </div>
    );
}
export default App;

index.js:

import React, {useState} from 'react';
import ReactDOM from 'react-dom';
import App from "./app";
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from "react-apollo";

const client = new ApolloClient({
  uri: 'https://countries.trevorblades.com'
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
);

Я новичокв GraphQl и Apollo и не знаю, что может быть причиной этой ошибки.

Обновление

Как предложил @Joseph, я извлек компонент из приложения и использовал useQuery,и теперь код выглядит так:

Select.js:

import React, {useState} from 'react';

function Select(props) {
  const [country, setCountry] = useState('US');
  const onCountryChange = event => {
    setCountry(event.target.value); // already called within the function component
  };

  return (
    <select value={country} onChange={onCountryChange}>
      {props.countries.map(country => (
        <option key={country.code} value={country.code}>
          {country.name}
        </option>
      ))}
    </select>
  );
}
export default Select;

app.js:

import React from 'react';
import { Query } from "react-apollo";
import { gql } from "apollo-boost";
import { useQuery } from '@apollo/react-hooks';
import Select from './select';

const query = gql`
  {
    countries {
      name
      code
    }
  }
`;

function App() {
  const { loading, error, data } = useQuery(query);

  return (
    <div className="App">
      <>
       {loading && <p>Loading...</p>}
       {error &&  <p>{error.message}</p>}
       <Select countries={data.countries} />
      </>
    </div>
  );
}
export default App;

Без изменений в index.js, но я все ещеполучить ту же ошибку.

Обновление 2:

Мне не хватало установки @apollo/react-hooks, но когда я установил ее, я получил новую ошибку:

Не удалосьне найти "клиента" в контексте или передан в качестве опции. Оберните корневой компонент в или передайте экземпляр ApolloClient через параметры.

Обновление 3:

Это долго, но я импортировал ApolloProvider из @apollo/react-hooksв index.js, чтобы исправить последнюю проблему:

import { ApolloProvider } from "@apollo/react-hooks";

И теперь я получаю

TypeError: данные не определены

В этой строкеapp.js:

  <>
   {loading && <p>Loading...</p>}
   {error &&  <p>{error.message}</p>}
   <Select countries={data.countries} />  // <= This line causes error
  </>
...