캐시를 사용하여 페이지 새로 고침 없이 데이터 캡처

5487 단어 reactgraphql

데모



문제 해결 목표



React todo-list 개발 페이지에서 데이터는 데이터베이스의 CRUD와 동기적으로 업데이트될 수 없습니다. 사용자는 최신 정보를 얻으려면 브라우저를 새로 고쳐야 하므로 브라우저가 멈춥니다. 여기서는 임시 데이터 저장 위치인 캐시를 사용하고 문제 해결 예제를 만들기 위해 todo-list 생성/삭제를 사용합니다.

전제 조건



  • GraphQL 클라이언트

  • urql : GraphQL 클라이언트
  • @urql/exchange-graphcache: 캐시 설정용

  • graphql-tag : GraphQL 쿼리 구문 분석을 위한 유틸리티
  • React/react-bootstrap (선택 사항)


  • 개념 코드



    ㅏ. 구성 요소 설정, GraphQL 쿼리 생성/삭제


    code .\src\components\todo.js
    import React from 'react'
    import gql from 'graphql-tag';
    import { useQuery, useMutation } from 'urql';
    import { InputGroup, FormControl, Button, Col, Row, Alert, Spinner } from 'react-bootstrap'; //optional
    
    export const FEED_QUERY = gql` //show latest info
      query{
        info{
            id
            title
          }
      }
    `;
    
    const UPSERT_POST = gql` //exexute todo create 
      mutation upsertPost( $postId:ID!, $title: String!) {
        upsertPost( postId: $postId, title: $title) {
          id
          title
        }
      }
    `
    
    const DELETE_POST = gql`
      mutation deletePost($postId:ID!) {
        deletePost(postId: $postId) {
          id
        }
      }
    `
    
    const PostForm = (props) => {
      //Upsert Section
      let postId = 0
      const [title, setTitle] = React.useState('')
    
      const [upsertState, executeUpsert] = useMutation(UPSERT_POST)
      const upsert = React.useCallback(() => {
        if (title.length !== 0 && title.length <= 30) { executeUpsert({ postId, title }); }
      }, [executeUpsert, postId, title])
    
      return (
        <Col sm={8}>
          <InputGroup className="mb-3">
            <FormControl
              placeholder='Add Todo...'
              aria-label="Recipient's username"
              aria-describedby="basic-addon2"
              maxLength="30"
              value={title}
              onChange={e => setTitle(e.target.value)}
            />
            <InputGroup.Append>
              <Button
                variant="outline-secondary"
                disabled={upsertState.fetching}
                type="submit"
                onClick={() => { upsert(); setTitle('') }}
              >Add</Button>
            </InputGroup.Append>{'  '}
          </InputGroup>
        </Col>
      )
    }
    
    function Post({ post }) {
      //Delete Section
      const postId = post.id
      const [deleteState, executeDelete] = useMutation(DELETE_POST)
      const del = React.useCallback(() => {
        executeDelete({ postId })
      }, [executeDelete, postId])
    
      return (
        <Col >
          <Alert variant="light" disabled={deleteState.fetching} onClose={() => { del(); }} dismissible>
            <p>{post.title}</p>
          </Alert>
        </Col>
      )
    }
    
    
    
    const PostList = () => {
      const [result] = useQuery({ query: FEED_QUERY })
      const { data, fetching, error } = result
    
      if (fetching) return <><Spinner animation="border" role="status"><span className="sr-only">Loading...</span></Spinner></>
    
      if (error) return <div>Error</div>
    
      const postsToRender = data.info
      return (
        <>
          {postsToRender.map(post => <Post key={post.id} post={post} />)}
        </>
      );
    };
    
    const Todo = (props) => {
      return (
        <>
          <br></br>
          <Row className="justify-content-md-center">
            <PostForm />
          </Row>
          <hr></hr>
          <Row className="justify-content-md-center">
            <PostList />
          </Row>
        </>
      )
    
    }
    
    export default Todo
    

    비. 캐시 설정


    code .\src\index.js
    //...React setting
    import { Provider, Client, dedupExchange, fetchExchange } from 'urql'
    import { cacheExchange } from '@urql/exchange-graphcache'
    import { FEED_QUERY } from './components/todo.js'
    
    const cache = cacheExchange({
      updates: {
        Mutation: { 
          upsertPost: (result, args, cache, info) => {  //execute create todo 
            cache.updateQuery({ query: FEED_QUERY }, data => { //update the latest information in cache 
              if (data !== null) {
                data.info.unshift(result.upsertPost);
                return data;
              } else {
                return null
              }
            });
          },
          deletePost: (result, args, cache, info) => { // execute delete todo
            cache.invalidate({ __typename: 'Post', id:  result.deletePost.id }); //delete todo in cache
          },
        },
      },
    });
    
    const client = new Client({
      url: '/',
      fetchOptions: () => {
        //...your fetch setting
      },
      exchanges: [dedupExchange, cache, fetchExchange],
    }) 
    
    ReactDOM.render(
      <Provider value={client}>
        <App />
      </Provider>,
      document.getElementById('root')
    )
    
    serviceWorker.unregister();
    
    

    노트



    할 일 목록은 demo 에서 사용자 관련 데이터를 가져오며 코드는 여기에 표시되지 않습니다. 캐시 효과를 경험하기 위해 할 일 전용 코드를 작성할 수 있습니다.

    좋은 웹페이지 즐겨찾기