React + GraphQL: не удалось найти «клиента» в контексте или передать как опцию - PullRequest
1 голос
/ 22 октября 2019

Я пытаюсь использовать React + GraphQL для создания простого блога, следуя инструкциям в этой статье . Однако, в отличие от статьи, мой блог не живет в App.js, а является дочерним компонентом. Кроме того, я не использую предложенный сервис GraphCMS, а вместо этого подключаюсь к базе данных Mongo.

Сервер GraphQL работает нормально. Я могу запросить его самостоятельно и при другой реализации получить все сообщения. Я отказался от этого подхода из-за его чрезмерной сложности.

При этом я постоянно получаю следующую ошибку. Это происходит каждый раз, когда я включаю <Landing /> в blog.js.

Uncaught Invariant Violation: Could not find "client" in the context or passed in as an option.

Я осмотрелся и нашел несколько решений, ни одно из которых не помогло мне.

  1. <ApolloProvider> не переносит graphql(DATA_QUERY) - я пытался реализовать этот метод вплоть до дочернего компонента, чтобы не повлиять.
  2. Удаление установленных модулей / проверка на несовпадение версий. - Без видимых различий.

    • Попытка ApolloProvider для обоих react-apollo и @apollo/react-hooks.
  3. Оберните родительский компонент с помощью ApolloProvider - Не отличается от # 1, в предложении. Не уверен, если на практике все по-другому.

Любая помощь очень ценится! Заранее спасибо !!


index.js

// @ts-check
import React from 'react';
import ReactDOM from 'react-dom';
import { StoreProvider } from './context/StoreContext';
import ApolloClient from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloProvider } from '@apollo/react-hooks';
import * as serviceWorker from './serviceWorker';

import App from './app';

// Have tried both with and without `/graphql` appended
const API = 'http://localhost:4000';
// const API = 'http://localhost:4000/graphql';

const client = new ApolloClient({
  link: new HttpLink({ uri: API }),
  cache: new InMemoryCache()
});


const Index = () => {
  return (
    <StoreProvider> // Used elsewhere; removing made no difference
      <ApolloProvider client={client}>
        <App />
      </ApolloProvider>
    </StoreProvider>
  );
}

ReactDOM.render(<Index />, document.getElementById('root'));
serviceWorker.unregister();

app.js

import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';

import NavBar from './routes/nav/navbar';
import Home from './routes/home/home';
import Blog from './routes/blogger/blog';


const App = () => {
  return (
    <Router>
      <NavBar />
      <div className="App">
        <Route path="/" exact component={Home} />
        <Route path="/blog/" component={Blog} />
      </div>
    </Router>
  );
};

export default App;

blog.js

import React from 'react';
import Header from './header';
import PostsWrapper from './landing';

const Blog = () => {
  return (
    <main>
      <Header />
      <PostsWrapper />  // <== issue is here
    </main>
  )
}

export default Blog;

landing.js

import React from 'react';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';

const Landing = ({ data: { loading, blogPosts } }) => {

  if (!loading) {
    return (
      <div className="wrapper">
        {blogPosts.map(post => (
          <article className="content" key={post._id}>
            <h2>{post.title}</h2>
            <p dangerouslySetInnerHTML={{ __html: post.description }} />
          </article>
        ))}
      </div>
    );
  }
  return <h2>Loading Posts...</h2>
};

const blogPosts = gql`
  query {
    blogPosts {
      _id
      title
      description
    }
  }
`;

const PostsWrapper = graphql(blogPosts)(Landing);
export default PostsWrapper;

package.json - соответствующие биты

"@apollo/react-hooks": "^3.1.3",
    "apollo-boost": "^0.4.4",
    "apollo-cache-inmemory": "^1.6.3",
    "apollo-client": "^2.6.4",
    "apollo-link-http": "^1.5.16",
    "react-apollo": "^3.1.3",
    "react": "^16.10.2",
    "react-bootstrap": "^1.0.0-beta.14",
    "react-dom": "^16.10.2",
    "react-router": "^5.1.2",
    "react-router-dom": "^5.1.2"

РЕДАКТИРОВАТЬ

Ошибка, которая отображается при наведении указателя мыши на (Landing) на graphql(blogPosts)(Landing) в Landing.js. В созданной мною версии песочницы нет ошибки, соответствующей образцу статьи. Подходит мое приложение к песочнице, но затем генерируется эта ошибка.

Пробовал несколько онлайн-решений, включая this безрезультатно.

const Landing: ({ data: { loading, blogPosts } }: {
    data: {
        loading: any;
        blogPosts: any;
    };
}) => JSX.Element

Argument of type '({ data: { loading, blogPosts } }: { data: { loading: any; blogPosts: any; }; }) => Element' is not assignable to parameter of type 'ComponentType<Partial<DataProps<{}, {}>> & Partial<MutateProps<{}, {}>>>'.
  Type '({ data: { loading, blogPosts } }: { data: { loading: any; blogPosts: any; }; }) => Element' is not assignable to type 'FunctionComponent<Partial<DataProps<{}, {}>> & Partial<MutateProps<{}, {}>>>'.
    Types of parameters '__0' and 'props' are incompatible.
      Type 'PropsWithChildren<Partial<DataProps<{}, {}>> & Partial<MutateProps<{}, {}>>>' is not assignable to type '{ data: { loading: any; blogPosts: any; }; }'.
        Types of property 'data' are incompatible.
          Property 'blogPosts' is missing in type 'QueryControls<{}, {}> & Partial<{}>' but required in type '{ loading: any; blogPosts: any; }'.ts(2345)

1 Ответ

0 голосов
/ 22 октября 2019

Ваш graphql HOC импортируется из react-apollo, но используемый вами ApolloProvider импортируется из @apollo/react-hooks. Поскольку это разные пакеты, контекст, который создает ваш провайдер, не совпадает с тем, что ищет HOC. Даже если вы используете хуки, вам вообще не понадобится зависимость @apollo/react-hooks. Всего:

import { ApolloProvider } from 'react-apollo'
import { graphql, useQuery, Query /* etc. */ } from 'react-apollo'
...