캐시를 사용하여 페이지 새로 고침 없이 데이터 캡처
데모
문제 해결 목표
React todo-list 개발 페이지에서 데이터는 데이터베이스의 CRUD와 동기적으로 업데이트될 수 없습니다. 사용자는 최신 정보를 얻으려면 브라우저를 새로 고쳐야 하므로 브라우저가 멈춥니다. 여기서는 임시 데이터 저장 위치인 캐시를 사용하고 문제 해결 예제를 만들기 위해 todo-list 생성/삭제를 사용합니다.
전제 조건
React todo-list 개발 페이지에서 데이터는 데이터베이스의 CRUD와 동기적으로 업데이트될 수 없습니다. 사용자는 최신 정보를 얻으려면 브라우저를 새로 고쳐야 하므로 브라우저가 멈춥니다. 여기서는 임시 데이터 저장 위치인 캐시를 사용하고 문제 해결 예제를 만들기 위해 todo-list 생성/삭제를 사용합니다.
전제 조건
GraphQL 클라이언트
urql : GraphQL 클라이언트
graphql-tag : GraphQL 쿼리 구문 분석을 위한 유틸리티
개념 코드
ㅏ. 구성 요소 설정, 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 에서 사용자 관련 데이터를 가져오며 코드는 여기에 표시되지 않습니다. 캐시 효과를 경험하기 위해 할 일 전용 코드를 작성할 수 있습니다.
Reference
이 문제에 관하여(캐시를 사용하여 페이지 새로 고침 없이 데이터 캡처), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/pcreem/use-cache-to-catch-data-without-page-refresh-1c5e
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
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
//...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 에서 사용자 관련 데이터를 가져오며 코드는 여기에 표시되지 않습니다. 캐시 효과를 경험하기 위해 할 일 전용 코드를 작성할 수 있습니다.
Reference
이 문제에 관하여(캐시를 사용하여 페이지 새로 고침 없이 데이터 캡처), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pcreem/use-cache-to-catch-data-without-page-refresh-1c5e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)