Combinando Redux y GraphQL con un ejemplo simple

Intentemos conectar Redux y GraphQL sin usar Apollo Client o Relay. Esto es más fácil de lo que parece.

Que es GraphQL

GraphQL para el cliente es solo una solicitud POST con un formato de cuerpo especial:

DESCANSO

GraphQL

OBTENER / libros / id

POST / graphql

query{ book(id) {} }

POST / libros

{…}

POST / graphql

mutation{ addBook() {...} }

ACTUALIZAR / libros / id

{…}

POST / graphql

mutation{ updateBook(id) {...} }

BORRAR / libros / id

POST / graphql

mutation{ deleteBook(id) {} }

GraphQL sin Apollo Client (y Relay)

Apollo-client GraphQL. , . Redux . .

Apollo Client :

const graphqlAPI = (query, variables) => fetch("/graphql", {
    method: "POST",
    body: JSON.stringify({ query, variables })
});

redux-toolkit

redux — redux-toolkit. — . :

, .

// booksSlice.js
import {
  createEntityAdapter,
  createAsyncThunk,
  createSlice
} from "@reduxjs/toolkit";

//      .

// createEntityAdapter    
//  ,      
// (addOne, addMany, updateOne, removeOne, setAll, ...), 
const books = createEntityAdapter();

// createAsyncThunk     .
// ,    API.
// getBooks    actions,     .
export const getBooks = createAsyncThunk("get books", async () => 
  await graphqlAPI(`
    query {
      books  {
        id
        title
      }
    }
  `)
);

export const addBook = createAsyncThunk("add book", ({ title }) =>
  graphqlAPI(`
    mutation ($title: string!){
      add_book(objects: { title: $title }) {
        id
        title
      }
    }
  `, { title })
);

// createSlice —   createAction  createReducer.
//      .
export const booksSlice = createSlice({
  name: "books",
  initialState: books.getInitialState(),
  extraReducers: {
    //     getBooks
    [getBooks.fulfilled]: (state, action) => {
      // setAll    createEntityAdapter
      books.setAll(state, action.payload);
    },
    //     addBook
    [addBook.fulfilled]: (state, action) => {
      // addOne    createEntityAdapter
      books.addOne(state, action.payload);
    },
  },
});

// createEntityAdapter    
// (selectIds, selectById, selectAll, ...)
export const booksSelectors = books.getSelectors((s) => s.books);

export default booksSlice.reducer;
// index.js
import { useDispatch, useSelector } from "react-redux";
import { getBooks, addBook, booksSelectors } from "./booksSlice";

export function Books() {
  const dispatch = useDispatch();

  // booksSelectors.selectAll    createEntityAdapter
  const books = useSelector(booksSelectors.selectAll); 

  useEffect(() => {
    dispatch(getBooks());
  }, [dispatch]);

  return (
    <div>
      <button onClick={() => dispatch(addBook({ title: "New Book" }))}>
        Add book
      </button>
      <ul>
        {books.map((b) => <li key={b.id}>{b.title}</li>)}
      </ul>
    </div>
  );
}

Redux , GraphQL. Apollo Client Relay.

Redux .

:

npx create-react-app my-app --template redux

Typescript:

npx create-react-app my-app --template redux-typescript

fetch graphql-request.



GraphQL .

hasura prisma.




All Articles