Добро пожаловать в часть 3 серии. Вы можете найти часть-2 здесь.

Эта серия была вдохновлена ​​этим уроком YouTube от freecodecamp.

Мы добавили еще двух авторов и несколько их книг, мутациями из части-2.

Теперь мы обновим наши операторы возврата, чтобы наши запросы снова работали. Теперь они содержат методы mongodb для получения данных. Итак, давайте отредактируем наш schema.js.

…
…
const BookType = new GraphQLObjectType({
    name: 'Book',
    fields: ( ) => ({
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        genre: { type: GraphQLString },
        author: {
            type: AuthorType,
            resolve(parent, args){
                //return authors.find(item => item.id === parent.authorId);
                return Author.findById(parent.authorId);
            }
        }
    })
});

const AuthorType = new GraphQLObjectType({
    name: 'Author',
    fields: ( ) => ({
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        age: { type: GraphQLInt },
        books: {
            type: new GraphQLList(BookType),
            resolve(parent, args){
                //return books.filter(obj => obj.authorId === parent.id);
                return Book.find({authorId: parent.id});
            }
        }
    })
});

const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
        book: {
            type: BookType,
            args: { id: { type: GraphQLID } },
            resolve(parent, args){
                //return books.find(item => item.id === args.id);
                return Book.findById(args.id);
            }
        },
        author: {
            type: AuthorType,
            args: { id: { type: GraphQLID } },
            resolve(parent, args){
                //return authors.find(item => item.id === args.id);
                return Author.findById(args.id);
            }
        },
        books: {
            type: new GraphQLList(BookType),
            resolve(parent, args){
                //return books;
                return Book.find({});
            }
        },
        authors: {
            type: new GraphQLList(AuthorType),
            resolve(parent, args){
                //return authors;
                return Author.find({});
            }
        }
    }
});
…
…

Теперь давайте проверим, правильно ли работают наши запросы. Первый запрос — получить все книги.

Следующий — получить всех авторов с их книгами.

Далее, это получить подробную информацию о книге

И последнее, чтобы получить информацию об авторе

Теперь в нашей логике есть небольшая проблема. Мы можем добавить новую книгу или автора с меньшим количеством полей. Рассмотрим приведенный ниже случай, когда мы добавляем книгу только с ее названием.

Мы также можем проверить в mongoDB.

Теперь, чтобы избежать этого, мы добавляем новое свойство GraphQL GraphQLNonNull.

Итак, откройте файл schema.js и внесите изменения, выделенные жирным шрифтом.

…
…
const { GraphQLObjectType, GraphQLString, GraphQLSchema, GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull } = graphql;
…
…
const Mutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        addAuthor: {
            type: AuthorType,
            args: {
                name: { type: new GraphQLNonNull(GraphQLString) },
                age: { type: new GraphQLNonNull(GraphQLInt) }
            },
            resolve(parent, args){
                let author = new Author({
                    name: args.name,
                    age: args.age
                });
                return author.save();
            }
        },
        addBook: {
            type: BookType,
            args: {
                name: { type: new GraphQLNonNull(GraphQLString) },
                genre: { type: new GraphQLNonNull(GraphQLString) },
                authorId: { type: new GraphQLNonNull(GraphQLID) }
            },
            resolve(parent, args){
                let book = new Book({
                    name: args.name,
                    genre: args.genre,
                    authorId: args.authorId
                });
                return book.save();
            }
        }
    }
});
…
…

Теперь, если мы перейдем к нашему Graphiql, мы не сможем ничего добавить без обязательных полей.

Далее мы добавим интерфейсную логику, которая представляет собой React в нашем приложении. Итак, перейдите в свой корневой каталог и создайте клиент с помощью create-react-app.

Затем мы запускаем наш реагирующий клиент.

Теперь у нас есть клиент, работающий на порту 3000, и сервер, работающий на порту 4000.

Затем мы очищаем часть мусора, который поставляется с приложением React. В папке src client удалите все, кроме App.js, index.js и

Кроме того, используйте простой index.js, как показано ниже.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

Теперь нужно изменить App.js, как показано ниже.

import React from 'react';


function App() {
  return (
    <div className="main">
      <h1>Top books to Read</h1>
    </div>
  );
}

export default App;

И index.css, как показано ниже.

body {
  font-family: "Helvetica Neue", sans-serif;
}

Это отобразит наше реагирующее приложение, как показано ниже.

Теперь создайте новую папку components внутри каталога src и добавьте в нее файл BookList.js.

Далее мы добавим компонент на основе класса в BookList.js.

import React, { Component } from 'react'

class BookList extends Component {
  render() {
    return (
      <div>
          <ul className="book-list">
            <li>Book Name</li>
          </ul>
      </div>
    )
  }
}

export default BookList;

Затем добавьте этот компонент в App.js.

import React from 'react';
import BookList from './components/BookList';

function App() {
  return (
    <div className="main">
      <h1>Top books to Read</h1>
      <BookList />
    </div>
  );
}

export default App;

Нам понадобится клиент GraphQL для связи, наш сервер GraphQL, и тот, который мы будем использовать, — это Apollo.

Продолжайте, остановите свой клиент и установите следующие пакеты, необходимые для клиента graphql.

npm install apollo-boost react-apollo graphql --save

Примечание. Столкнулся с проблемой после npm install apollo-boost react-apollo graphql — сохраните. Нашел решение онлайн и заключался в том, чтобы удалить папку node_modules внутри клиента и выполнить установку пряжи.

Теперь давайте начнем использовать graphql. Мы отредактируем наш файл BookList.js, чтобы получить данные с сервера graphql.

import React, { Component } from 'react';
import { gql } from 'apollo-boost';
import { graphql } from 'react-apollo';

const getBooksQuery = gql`
    {
        books {
            name
            id
        }
    }
`;

class BookList extends Component {
  render() {
    console.log(this.props);
    return (
      <div>
          <ul className="book-list">
            <li>Book Name</li>
          </ul>
      </div>
    )
  }
}

export default graphql(getBooksQuery)(BookList);

При проверке того, что мы получаем через console.log, мы получаем неприятную ошибку cors.

Итак, мы установим модуль cors на наш сервер. Остановите сервер и установите его с помощью npm.

Теперь перейдите к app.js внутри папки server и добавьте cors

const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./schema/schema');
const mongoose = require('mongoose');
const cors = require('cors');
const app = express();

app.use(cors());

mongoose.connect('mongodb://nabsNew:[email protected]:59546/graphql-react');
mongoose.connection.once('open', () => {
    console.log('Conneted to database');
});

app.use('/graphql', graphqlHTTP({
    schema,
    graphiql: true
}));

app.listen(4000, () => {
    console.log('Listening at port 4000');
});

Теперь обновите приложение, и вы не увидите ошибку.

Теперь, когда мы получаем наши книги правильно, мы обновим наш BookList.js, чтобы книги отображались на экране.

import React, { Component } from 'react';
import { gql } from 'apollo-boost';
import { graphql } from 'react-apollo';

const getBooksQuery = gql`
    {
        books {
            name
            id
        }
    }
`;

class BookList extends Component {
    displayBooks() {
        var data = this.props.data;
        if (data.loading) {
            return (<div>Loading books...</div>);
        } else {
            return data.books.map(book => {
                return (
                    <li key={book.id}>{book.name}</li>
                );
            })
        }
    }

    render() {
        console.log(this.props);
        return (
            <div>
                <ul className="book-list">
                    {this.displayBooks()}
                </ul>
            </div>
        )
    }
}

export default graphql(getBooksQuery)(BookList);

Здесь мы добавили метод displayBooks() для отображения книг. Если вы заметили, что console.log в предыдущей части, первый раз отображается пустой список, когда загрузка имеет значение true. Мы получаем список книг только во второй части, когда loading имеет значение false.

Это завершает наш звонок, и мы получаем все наши книги, отображаемые в приложении.

На этом заканчивается часть 3 серии. Вы можете найти код здесь, в ссылке на github.

Финальную часть-4 вы можете найти здесь.