React 写中后台应用 最佳实践

一 不建议使用 useUncontrolled

组件封装,最好同时支持受控使用和非受控使用(预防未来抽离组件 或者用于循环场景), 一般组件库会使用useUncontrolled, 但是业务代码最好不要

jsx 复制代码
const [state, setState] = useControllableValue<string>(props, {  
const

此类 hook 返回的 setState 支持传入值, 好一些的会支持传入函数,

此类 hook,一般受控非受控的标志是, value === undefined, 但是 ahooks 不是这样,

但是, 官方 useState const [state,setState] = useState() 返回的 setState 还支持批量更新,也就是传入回调函数,多次调用 setState, 但是这个 hook 是永远无法支持的,至少至今没见过

正确的做法: useState + useEffect

jsx 复制代码
const [state,setState] = useState(props.value)
useEffect(()=>{
setState(props.value)
},[props.value])

<Child value>

当然, 如果你的应用足够复杂,可以再次封装,参考xyflow

jsx 复制代码
useStoreUpdater<Node[]>(nodes, setNodes);

当然也可以显式表达非受控,使用 defaultvalue, 参考

jsx 复制代码
useEffect(() => {
    const edgesWithDefaults = defaultEdges?.map((e) => ({ ...e, ...defaultEdgeOptions }));
    setDefaultNodesAndEdges(defaultNodes, edgesWithDefaults);

    return () => {
      reset();
    };
  }, []);

二 父组件的状态,不要拆散后传给子组件,且尽量不要有多对

  1. 不要拆散,是因为当数据很复杂时, 书写onValueChange函数时,容易出问题, 这算是一个好习惯吧
  2. 不要有多对,是因为某些需求下,需要传入回调来支持批量更新, 但是万一你使用了 useUncontrolled,那就得重构,而我们封装组件应该尽量满足各种使用情况
jsx 复制代码
const [state,setState] = useState()

<Child  readonly={state.reanonly}  value={state.value} onValueChange={state.value=x}/>

// Child.tsx
useRequest([readonly,value]) // 模拟读取
const onChange = (newVal)=>{ // 模拟修改
 onValueChange(newVal)
}

三 Form组件 最好借助框架使用 Form + useForm

jsx 复制代码
const [state,setState] = useState()
 
const fetch = (values)=> {
console.log(state) // state 是陈旧的,所以需要通过参数传入, 
}

<Form onSubmit={values=> {
 setState(values); // 一次更新太多变量,跟容易出 bug, 
 fetch(values);
 setPage(1) // 假如fetch 需要 page, 那么page 也要放到形参里, 这是会无限增加附加度的方式
} } />

最好使用 useForm, 下降复杂度

jsx 复制代码
const [form] = useForm()

const fetch = ()=> { // 不需要任何参数了
const values =  form.getValues() 
}

<Form form={form} onSubmit={values=> {
form.setFieldsValue({
...values,
page:1
})
fetch();

} } />

类似于 useStateRef, 另外使用 antd 的Form组件,是因为 onValuesChange是由用户操作才会触发, 而 mantine-form 没有这个 api

jsx 复制代码
const [form] = useForm() // mantine 没有 onValuesChange, 你只能模拟

// 这段代码跟下面的将造成死循环, 使用 JSON.stringify hack 处理, 在极端场景下也会有问题

useEffect(()=>{
form.setValues(form.values)
},[form.values])

useEffect(()=>{
onChange(form.values)
},[form.values])

<Form form={form} >

四 使用 ahooks 的 useRequest

由于页面不总是查询按钮触发的查询, 或者请求可能在子组件,拿不到 loading,所以无法给按钮正确的 loading 效果, 我们需要保证数据的正确,所以最好使用 ahooks 的 useRequest

五 使用 SWR 来请求下拉列表

在复用下拉列表的场景里, 比如table 里行内编辑, 多个页面共用选择器等, 可以显著增加响应速度 不过注意接口最好是get, 因为类似的 react-query 和 swr, onfetch 推崇 restfulapi, 对 get 支持最好,比如重新校验只支持get, 使用时注意, 黑盒很多,不要过度滥用

六 弹窗编辑

推荐使用 antd 的 Form 来处理,initialValues 里放数据缺失时的默认值,不要放新增按钮的数据, 因为这将被用到合并, finalValue = {...initialValues, ...row}, 比自己写要轻松一些, 另外setValues 总是增加值, 不支持reset, 所以你的 Modal 最好是 {show? <Modal/>: null} 来销毁

七 尽量写完整的TS

需求变更时, 需要重构代码,字段增减等, 有个 ts 的话,会告诉你哪个文件要修改, 效率和安全性能提升特别特别多,特别是二次封装的组件, 优先级强于业务代码

相关推荐
有梦想的刺儿16 分钟前
webWorker基本用法
前端·javascript·vue.js
cy玩具37 分钟前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161771 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test2 小时前
js下载excel示例demo
前端·javascript·excel
Yaml42 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事2 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶2 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo2 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v2 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
知孤云出岫2 小时前
web 渗透学习指南——初学者防入狱篇
前端·网络安全·渗透·web