DaZeng:GraphQL、useQuery、useMutation、useLazyQuery的基础使用

前言

上周五的毕业典礼举行完了,工作也落实了有一段时间了,总结一下最近学到的技术以及一些存在的问题总是好的。这段时间实习工作的技术栈是react+ts+gql,也是我第一次接触gql,用了感觉真香,在使用过程中主要是配合react的函数式组件进行使用,作用简而言之就是查询然后发请求返回数据,替代了axios,fetch和原生的ajax请求,也不能叫替代吧就是大体作用相差不大,比起上面的方法,它不用再去书写请求头,方法类型啊等等。

GraphQL(gql)

在最开始使用的时候看了不是博文,这篇GraphQL入门到实践说实话还不错,写的概念上还是很规范也通俗易懂,基本大体浏览一下就知道gql是什么大体使用就清楚了,但是对接我自己的项目肯定还是有不同的地方。

接口文档以前自己做项目看的都是swigger,来这边之后因为要配合gql的使用,接口文档就是这样的:
在这里插入图片描述
上面的QUERIES,就是类似于我们的GET请求,下面的MUTATIONS就是类似于POST请求,在具体的gql使用上代码如下:

import { gql } from "@apollo/client"
class Api {
  // 不需要传参的查询,查后端adminInfo接口返回id和listTask接口默认传skip为0,返回status
  adminInfo = gql`
  {
    adminInfo {
      id
    }
    listTask(
      skip:0
    ){
      status
    }
  }
  `
  // 查询带有默认值,可进行传参或直接查询
  groupList = gql`
  query(
    $key: String = ""
    $limit: Int = 10
  ) {
    list: groupList(
      key:$key,
      limit:$limit,
    ) {
      founder{
        lastLogin{
          str
        }
        id
      } 
    }
    
    groupCount(
      key:$key
    )
    
    adminList(
      limit:$limit
    ){
      id
    }
    
    baseData {
      followTags
    }
  }
  `

  
  //类似于POST !表明为必传项 EnumType是枚举类型
  modifyGroupStatus = gql`
  mutation(
    $note: String!
    $groupId: String!
    $status: GroupCrmStatusEnumType!
    $tag: String
  ){
    modifyGroupStatus(
      note:$note
      groupId:$groupId
      status:$status
      tag:$tag
    ){
      id
    }
  }
  `

  //[xxxxxx]传的是一个数组,每个数组是一个对象(具体看后台约定为什么)
  saveFaqType = gql`
  mutation(
    $args:[saveFaqTypeInput]
  ){
    saveFaqType(args:$args){
      id
      questions{
        question
      }
    }
  }
  `
}

const api = new Api()
export default api

useQuery

useQuery就是配合gql进行查询的操作,但是在一个函数式组件中只能用一个useQuery,所以想要获取多个接口的数据要么拆分为多个函数式组件,要么写在gql中拼接返回数据。

import { useQuery } from "@apollo/client";
import api from "src/services/api";

export default function Tracked() {
	// data 查询的结果
	// refetch用于重新进行useQuery的请求
	// loading 加载中 返回的error信息
	// fetchPolicy: "no-cache" 不缓存查询的结果

  // 不传值的查询 const { loading, error, data } = useQuery(api.adminInfo)
  const { data, refetch, loading,error } = useQuery(api.groupList, { variables: { limit: 10, key: '我是关键字' },fetchPolicy: "no-cache" })

	//一般data要配合useState保存数据

   //分页点击
  const pageChange = (pageSize: number) => {
    refetch({ limit: pageSize, key: key })
  }
}

useLazyQuery

useLazyQuery 也是查询,它和useQuery的不同点在于useQuery是一进入某个组件就会自动去查询数据,且在一个函数组件中通常useQuery只有一个,而useLazyQuery则是事件触发时的查询,如按钮点击时。

import { useLazyQuery } from "@apollo/client";

const [exportOrders, { data: dataExport, error: errExport }] = useLazyQuery(api.purch.exportOrders, {
        onCompleted: someData => {
            // console.log('someData', someData)
            /* do your staff */
        }
    });

//也可以去监听里面数据的变化
useEffect(() => {
    if (dataExport) {
        // message.success('导出成功')
        console.log('dataImport', dataExport);
        /* do your staff */
    }
}, [dataExport])

//函数调用传参
const exportOut = (id: string) => {
        exportOrders({ variables: { fileId: id } })
    }

return (
 <Button className='out-btn' shape='round' onClick={() => { exportOut(item.id) }}>导出</Button>
)

useLazyQuery踩坑记录

当要去设置loading状态,如在函数组件中,查询出来的数据和上次相同则不会触发useEffect <连续点击进行查询的调用>

const [loading, setLoading] = useState(false) //点击查询按钮的loading
const [getList, getListRes] = useLazyQuery(api.list, { fetchPolicy: 'no-cache' });
const [resErr, setResErr] = useState<any>(null)

useEffect(() => {
  if (getListRes?.data) {
      let data = getListRes.data
      console.log('-res--', data);
      setList(data.list)
  }
}, [getListRes?.data])

// 获取列表信息
const getGoodsClearList = async (v: any) => {
    if (getListRes.called) {
    	//不是首次调用了 自定义loading
        setLoading(true)
        try {
            await getListRes.refetch(v)
        }
        catch (ex) {
            setResErr(ex)
        }
        setLoading(false)
    } else {
        //首次调用lazyQuery --> getListRes.loading生效
        getList({ variables: v })
    }
}

const okLoading = getListRes.loading || loading


// 异常处理
{
 getListRes?.error || resErr ?
    <div className='err-text'>
        <ErrorView error={resErr || getListRes.error} />
    </div>
    :
    <div>正常的显示数据</div>
}

useMutation

useMutation是可以在一个函数组件中多次使用的

import { useMutation } from "@apollo/client";
//封装的Mutation方法:
export async function invokeMutationFunction<TData = any, TVariables = OperationVariables>(
    mfunc: MutationFunction<TData, TVariables>,
    options?: MutationFunctionOptions<TData, TVariables>) {
        // console.log('invokeMutationFunction',options);
    try {
        return await mfunc.call(null, options)
    } catch (error) {
        showErrorMessage(error)
        return undefined
    }
}
//定义枚举类型
export enum GroupCrmStatusEnumType {
    INVALID = 'INVALID',
    // 无效客户
    DISTRIBUTION = 'DISTRIBUTION',
    // 待分配
    FOLLOW = 'FOLLOW',
    // 待跟进
    EFFECTIVE = 'EFFECTIVE'
    // 有效客户
}

export function GroupModalEffective(props:any) {
	let modifyState = {
	  note: '',
	  groupId: "",
	  status: '',
	  tag: ''
	}
    const [changeState] = useMutation<any, any>(api.modifyGroupStatus)
    const [saveFaqType] = useMutation<any, any>(api.saveFaqType)
    const handleOk = async () => {
      modifyState.groupId = tempArr.groupId
      modifyState.status = GroupCrmStatusEnumType.FOLLOW
      const res = await invokeMutationFunction(changeState, {
        variables: modifyState
      })
      let args: any = []
      fenleiArr.forEach((item, index) => {
          if (item.name != '') {
          	//具体看后台约定数组里面是什么对象就进行添加
              args.push({
                  order: index,
                  name: item.name,
                  id: item.id == undefined ? '' : item.id
              })
          }
      })
      const res = await invokeMutationFunction(saveFaqType, {
          variables: { args }
      })
    }
  //res就是后台返回的数据
}
 

include、skip的使用

include和skip在GraphQL中是相反的作用,include判断结果为真执行,反之不执行,在设置请求时候可自定义是否进行对应数据的查询,加快响应速度。

export default `query(
  $supplyId: String = ""
  $supplyInfoLoad: Boolean = true
){
  founder{
    supplyInfo(id:$supplyId)
    @include(if: $supplyInfoLoad){
      logo
      nickname
    }
  }
}`
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da Zeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值