一、案例背景
七镜在基于react编写页面时,发现一段每个页面都重复的graphql相关代码,代码如下:
// 标记1
const [dataNews, setDataNews] = useState<TGqlDimensionNews>({
code: 0, content: [], count: 0, msg: {fail: "", success: ""}
})
// 标记2
const [condNews, setCondNews] = useState<TCondType>({
page_after: 0,
page_size: 10,
order_by: "created_at",
sort_by: "desc",
detail: {},
keyword: {
},
table_name: "dimension_news",
})
// 标记3
//useGraphql
const [getDimensionNews, {data: dataDimensionNews, error}] = useLazyQuery(QUERY_DIMENSION_NEWS)
// 标记4
// useEffect:
useEffect(() => {
getDimensionNews({
variables: {
from_id: auth.data.base.id,
from_nickname: auth.data.account,
content: JSON.stringify(condNews)
}
})
.then(resp => {
let tmpData = {...resp.data.dimensionNews} as TGqlDimensionNews
// console.log("result:", tmpData.content[0].base_dimension.content)
if (tmpData.code === 200) {
setDataNews(tmpData)
}
})
.catch(e => {
console.log(e)
})
}, [condNews])
- 标记1:定义服务端数据接收过来的结构体
- 标记2:定义服务端数据获取的过滤条件
- 标记3:定义graphql数据获取的函数入口
- 标记4:通过graphql数据获取函数接收服务端数据,并存入保存页面数据的地方(dataNews)
我们知道,写代码的时候,面对第一个新需求,快速实现一段代码;面对第二个差不多的需求,针对刚刚那段代码,复制粘贴并做一些小小的修改;面对第三个差不多的需求,应当重构前面的代码。
二、优化方案
首先,技术实现肯定是基于 react hooks。详细代码如下:
import React, {useState, useEffect, useContext} from "react";
import {DocumentNode, useLazyQuery} from "@apollo/react-hooks";
import {
TCondType,
TResponseCommon
} from "../../register-center/graphql/graphql-types/graphql-types";
import {ContextAuth} from "../../register-center/context/auth/context-auth";
export interface useGraphqlGetProps {
cond: TCondType, // 接口参数
gql_schema_query: DocumentNode, // Graphql schema
gql_data_query_name: string, // 查询的表名
setData: React.Dispatch<React.SetStateAction<TResponseCommon>> // 设置查询结果
}
function useGraphqlQuery(props: useGraphqlGetProps): [TCondType, React.Dispatch<React.SetStateAction<TCondType>>] {
const [auth, setAuth] = useContext(ContextAuth) // 接口参数中的用户名和用户昵称的来源
const [cond, setCond] = useState<TCondType>(props.cond)
//useGraphql
const [getData, {error}] = useLazyQuery(props.gql_schema_query)
// useEffect
useEffect(() => {
if (!cond.table_name) {
console.error("please replace cond.table_name")
return
}
getData({
variables: {
from_id: auth.data.base.id,
from_nickname: auth.data.account,
content: JSON.stringify(cond)
}
})
.then(resp => {
let tmpData = {...resp.data[props.gql_data_query_name]}
// console.log("result:", tmpData.content[0].base_dimension.content)
if (tmpData.code === 200) {
props.setData(tmpData)
}
})
.catch(e => {
console.error(e)
})
}, [cond])
return [cond, setCond]
}
export default useGraphqlQuery
实现思路:
- 该hook的初始化依赖于传入的【接口参数】、【graphql schema】、【查询的表名】、【设置查询结果的函数】
- 该hook中的实现逻辑与之前代码一致。
- 替换之前的代码中与传入参数一致的地方。
三、优化结果
优化后计入数据的代码:
const [data, setData] = useState<TGqlDimensionApplicationCase>(initResponseCommon)
const [cond, setCond] = useGraphqlQuery({
cond: {
...initCond,
table_name: "dimension_application_case",
},
gql_schema_query: QUERY_DIMENSION_APPLICATION_CASE,
gql_data_query_name: "dimensionApplicationCase",
setData: setData
})
- 从优化前后的代码行数,可以看到代码量已经大大减少了,封装完毕。








网友评论