react-query modify server status request Mutation

通常用于创建/更新/删除数据或执行服务器副作用

(1)useMutation
	const mutation=useMutation((参数)=>{
		向服务器提起修改请求,如
		axios.get('/todos', {params:参数});
		return 修改后的返回结果
	},{可选配置属性})

			
	发起修改请求:
		方式一:
			mutaion.mutate(参数);
			其中:
			mutation.mutate函数是一个异步函数,这意味着你不能在事件回调中直接使用它,如果需要event,需要在外部包裹一个函数
	        const onSubmit = event => {
		      event.preventDefault()
		      mutation.mutate(new FormData(event.target))
		    }
		方式二:
			Pomise方式:
			const res=await mutation.mutateAsync参数);
		
		方式三:
			将mutaion存进缓存中,然后通过key调用
			queryClient.setMutationDefaults(key,{
				mutationFn:提交修改请求并返回结果的方法,
				...生命周期方法
			})
			const mutation = useMutation(key);
			mutation.mutate(参数);
		
		方式四:
			设置默认提交方法,即为方式三的声明版本
			new QueryClient({
			   defaultOptions: {
			     mutations:{	提交的默认配置
			     	mutationFn:设置mutation的默认方法
			     }
			   },
			})

	
	配置参数:
		{
			retry:3,	默认情况下不会在出错时提交,除了配置了retry选项
		}
			
    其他返回参数:
  		.status:状态字符串
		.isLoading:正在提交,对应status === 'loading'
	    .isError: 提交遇到一个错误,对应status === 'error'
	    .isSuccess: 提交成功且数据可用,对应status === 'success'
	    .isIdle:提交是空闲的或处于新鲜/重置状态,对应status === 'idle'
		
	    .error:如果提交处于isError状态,则可以通过error属性获取该错误。
	    .data:如果提交处于成功状态,则可以通过data属性获取返回的数据
	    .refetch:用于手动再次查询,在enabled:false时,调用refetch()才会开始查询
		
		.reset(), 清除提交返回的错误信息或数据

(2)useMutation生命周期
	方式一:
		useMutation(fn,{
			onMutate: variables => {	variables为给fn传递的参数
			  发起提交回调
		      return {name:'jeff'}
		    },
		    onError: (error, variables, context) => {	context为onMutate返回的内容
			  错误回调
		    },
		    onSuccess: (data, variables, context) => {	data为提交请求后返回的数据
		   	  成功回调
		      
		    },
		    onSettled: (data, error, variables, context) => {
		       在成功和失败回调之后触发的回调
		    },
		})
	
	方式二:
		mutation.mutate({
			onSuccess: (data, variables, context) => {
				...
			},
			onError: (error, variables, context) => {
				...
			},
			onSettled: (data, error, variables, context) => {
				...
			}
		})
		
(3)提交mutaion后,重新设置缓存中查询对应的内容
	重新设置缓存中的内部,比重新进行查询更能节省带宽
	如:
	 const mutation = useMutation('edit', {
		onSuccess: data => queryClient.setQueryData(key,data),
	 })
	自定义hook:
	 const useMutateTodo = () => {
	   const queryClient = useQueryClient()
	   return useMutation(editTodo, {
	     onSuccess: (data, variables) => {
	       queryClient.setQueryData(['todo', { id: variables.id }], data)
	     },
	   })
	 }
	 
(4)乐观数据更新,即错误回滚操作
	在提交的生命周期中,先获取到旧值,若发生了错误,则还是将旧值缓存
	useMutation(updateTodo, {
	   onMutate: async newTodo => {
	     await queryClient.cancelQueries('todos')	停掉所有可能在提交期间会覆盖掉数据的查询
	     const previousTodos = queryClient.getQueryData('todos')	获取缓存的旧值
	     return { previousTodos }	 将旧值返回给上下文context
	   },
	   onError: (err,variables, context) => {
	     queryClient.setQueryData('todos', context.previousTodos)	若发生错误,则继续缓存旧值
	   },
	   onSettled: () => {
	     queryClient.invalidateQueries('todos')	在提交成功/失败之后都进行重新查询更新状态
	   },
	 })

(5)匹配正在提交的mutaion,(当前测试会报错未找到方法)
	 await queryClient.isMutating()	获取正在提取的mutaion数量
	 await queryClient.isMutating({
	 	exact:true, 	精确匹配mutationKey
	 	fetching:true,	正在抓取的mutation,否则匹配未正在抓取的mutation
	 	predicate:(mutation)=>布尔值,	匹配返回true的mutation
	 	mutationKey:匹配key
	 })
	 

(6)useMutation的脱水和水化
	粗浅理解为:
		设备离线时将被暂停的mutation脱水,设备启动时水化后能再次执行被暂停的mutation
		即:当后台服务停止,前台被暂停的提交会在服务重启后再次执行
	
	
	import { dehydrate, hydrate} from 'react-query/hydration'
	
	(1)将mutation存进缓存中
		queryClient.setMutationDefaults(key,{
			mutationFn:提交修改请求并返回结果的方法,
			...生命周期方法
		})
	
	(2)提交
		 const mutation = useMutation(key);
		 mutation.mutate(参数)
   
   	(3)设备离线时,将被暂停的提交去水
   		 const state = dehydrate(queryClient)
  
  	(4)设备开启时,将提交水化然后重新提交
  		 hydrate(queryClient, state)
		 queryClient.resumePausedMutations()

Code example:
Submit dehydration and hydration:

import React,{
    
    useState,useEffect,useCallback,useMemo} from 'react';
import {
    
     QueryClient, QueryClientProvider, useQuery,useIsFetching, useInfiniteQuery,useMutation } from 'react-query'
import {
    
     ReactQueryDevtools } from 'react-query/devtools'
import {
    
     dehydrate, hydrate} from 'react-query/hydration'
import axios from 'axios';
import './query.css';

const queryClient = new QueryClient({
    
    

 })



const App = () => {
    
    
  
  return (
     <QueryClientProvider client={
    
    queryClient}>
      <Example />
      <ReactQueryDevtools initialIsOpen={
    
    false}  position='top-right' />
    </QueryClientProvider>
  )
}


function Example() {
    
    
  const [page, setPage] = useState(0);
  

  queryClient.setMutationDefaults('addTodo', {
    
    
    mutationFn: newTodo => axios.get('/movie', newTodo),
    retry: 3,
    
  })
  const mutation = useMutation('addTodo')


  const state = dehydrate(queryClient)
  hydrate(queryClient, state)
  queryClient.resumePausedMutations()
  console.log(state);
  console.log(mutation.data);

  return (
    <div>
    
      <button
        onClick={
    
    async () => {
    
    
          mutation.mutate({
    
     title: 'title' })
        }}
      >
        下一页{
    
    page}
      </button>
      
    </div>
  )
}


export default App

Guess you like

Origin blog.csdn.net/weixin_43294560/article/details/115000643