How to install & configure
yarn add react-query
const RootComponent = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: true, // React Query automatically requests fresh data for you in the background }, }, }) return (<QueryClientProvider client={queryClient}> <App /> </QueryClientProvider>) } ReactDOM.render(<RootComponent />, document.getElementById('root'))
Add devtools
By default, React Query Devtools are not included in production bundles when process.env.NODE_ENV === 'production'
, so you don’t need to worry about excluding them during a production build.
... import { ReactQueryDevtools } from 'react-query/devtools' const Bootstrap = () => { ... return ( ... <App /> <ReactQueryDevtools initialIsOpen={false} /> ... ) } ReactDOM.render(<RootComponent />, document.getElementById('root'))
How to request Rest API?
import { useQuery } from 'react-query'; import axios from 'axios'; export const fetchPosts = async () => { const { data } = await axios.get( 'https://jsonplaceholder.typicode.com/comments?postId=5' ); return data; }; const useFetchPosts = () => useQuery(['fetchPosts'], () => fetchPosts()); export default useFetchPosts;
const Home: FC<Props> = ({ navigation }) => { const { data, isLoading, isSuccess } = useFetchPosts(); if (isLoading) { console.log('=========isLoading', isLoading); } if (data) { console.log('=========data', data); } if (isSuccess) { console.log('=========isSuccess', isSuccess); } return (...) });
How to request graphQL?
Install
yarn add graphql graphql-request
Usage 1
// queries.js import { gql } from 'graphql-request' export const ONE_GRAPHQL_QUERY = gql` query getPost($postId: ID!) { getPost(_id: $postId) { _id content description title } } `
const graphQLClient = new GraphQLClient('https://graphql.abcd.com/', { method: 'POST', headers: { 'x-api-key': xxxxxxxxxx, 'content-type': 'application/json', }, }) ///////////////////// ///////////////////// export const fetchPost = async (postId) => { const response = await graphQLClient.request(ONE_GRAPHQL_QUERY, { id: postId, }) return response }
const Demo = ({ postId }) => { const { data, isLoading, error } = useQuery( ['fetchPost', postId], () => fetchPost(postId) ) if (data) { console.log(data) } return ( <div>{isLoading ? 'Loading...' : 'Done!'}</div> ) } export default Demo
How to trigger a fetch request with a button?
- Use refetch()
const { refetch: fetchSomething } = useQuery( ['fetchMyData', input], () => fetchMyData(input), { enabled: false, } ) function onClick(e) { fetchSomething() }
How to trigger create/ update/ delete data with a button?
- Method 1
import { GraphQLClient } from 'graphql-request' import { useMutation } from 'react-query' const graphQLClient = new GraphQLClient( process.env.API_GRAPHQL_ENDPOINT, { method: 'GET', headers: { Authorization: accessToken, }, } ) const updateUser = async (input) => { const response = await graphQLClient.request(UPDATE_USER_QUERY, { input, }) return response } export const useUpdateUser = () => { return useMutation( async (data) => { return await updateUser(data) }, { onMutate: (editedValue) => { // console.log(data, error, editedValue) }, onError: (error, editedValue) => { console.log(error, editedValue) }, onSettled: (data, error, editedValue) => { // console.log(data, error, editedValue) }, onSuccess: (data, variables) => { // console.log(data, variables) }, } ) }
// Use it in your component const { mutateAsync: updateUser, status: userUpdateStatus, isLoading: isLoadingUserUpdate, data: userUpdateData, error: userUpdateErr } = useUpdateNote() function onClickSaveUser() { const detail = getUserDetail(...) updateUser(detail) }
graphql-hasura-with-react-query-mutation
- Method 2
export const updateUserNote = async (input) => { const response = await graphQLClient.request(UPDATE_USER_QUERY, { input, }) return response }
const mutation = useMutation(async (note) => { return await updateBlackbookNote(note) }) function onClickSaveUser() { const detail = getUserDetail(...) mutation.mutate(detail) }
react-query.tanstack.com/guides/mutations
How to save fetched data into useState?
const YourComponent = () => { const [userList, setUserList] = useState(null) const { isLoading } = useQuery( ['fetchUserList'], () => fetchUserList(), { onSuccess: (data) => { setUserList(data) }, } ) ...
How to request paginated queries?
function Todos() { const [nextPageParam, setNextPageParam] = React.useState(0) const fetchProjects = (nextPageParam = 0) => fetch('/api/projects?page=' + nextPageParam).then((res) => res.json()) const { isLoading, isError, error, data, isFetching, isPreviousData, } = useQuery(['projects', nextPageParam], () => fetchProjects(nextPageParam), { keepPreviousData : true }) return ( <div> {isLoading ? ( <div>Loading...</div> ) : isError ? ( <div>Error: {error.message}</div> ) : ( <div> {data.projects.map(project => ( <p key={project.id}>{project.name}</p> ))} </div> )} {/* Pages */} <span>Current Page: {nextPageParam + 1}</span> <button onClick={() => setNextPageParam(old => Math.max(old - 1, 0))} disabled={nextPageParam === 0} > Previous Page </button>{' '} <button onClick={() => { if (!isPreviousData && data.hasMore) { setNextPageParam(old => old + 1) } }} // Disable the Next Page button until we know a next page is available disabled={isPreviousData || !data?.hasMore} > Next Page </button> {isFetching ? <span> Loading...</span> : null}{' '} </div> ) }
How to request infinite queries?
import { useInfiniteQuery } from 'react-query' const fetchProjects = (customParam, queryParam) => fetch('/api/projects?cursor=' + queryParam + '?category=' + customParam) function Projects({ customParam }) { const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, status, } = useInfiniteQuery('projects', ({ pageParam: queryParam }) => { // "pageParam" is returned from the "getNextParam" return fetchProjects(customParam, queryParam) }, { getNextPageParam: (lastPage, pages) => { const queryParam = lastPage.nextCursor // If no key is returned from last data, "false": no next page return queryParam ? queryParam : false }, }) return status === 'loading' ? ( <p>Loading...</p> ) : status === 'error' ? ( <p>Error: {error.message}</p> ) : ( <> {data.pages.map((group, i) => ( <React.Fragment key={i}> {group.projects.map(project => ( <p key={project.id}>{project.name}</p> ))} </React.Fragment> ))} <div> <button onClick={() => fetchNextPage()} disabled={!hasNextPage || isFetchingNextPage} > {isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Load More' : 'Nothing more to load'} </button> </div> <div>{isFetching && !isFetchingNextPage ? 'Fetching...' : null}</div> </> ) }
What the difference between react-query and apolloClient?
react-query doesn’t have normalized cache.
A “fully normalized cache” means that if multiple different queries return the same type of item with the same ID, it will only be stored once.
As an example, say you have a blog post app with /getPosts
and /getPost/:postId
endpoints. You make a request to /getPosts
, and also to /getPost/3
. Both endpoints return an item with {id: 3}
. Do you end up with one object in the cache with that ID, or two objects in different places?
With a normalized cache, the client determines that “both of these items are of type Post
, and both are ID 3″, so it only saves the one copy. With a non-normalized cache, the array of [{id: 1}, {id: 2}, {id: 3}]
from /getPosts
is saved separately from the {id: 3}
returned by /getPost/3
.
How to use json-server to simulate fake API call?
Install
sudo npm install -g json-server
Create fake response db.json
{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
Simulate fake API call
json-server --watch db.json --port 9000
Leave a Reply