「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」
Hope is a good thing, maybe the best of things. And no good thing ever dies—— 《The Shawshank Redemption》
前言
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。通过自定义 Hook,可以将组件逻辑提取到可重用的函数中。
最近在做一个业务代码,在一个 RadioGroup 的每个 Radio 后面渲染一个额外的 Field,作为 Form 的一个 FormItem,需要支持 FormItem 的自定义校验(包含错误状态的转换和错误信息定的显示)。而且在一个页面中会出现多个类型的 FormItem,这样就要保证每个组件内部的状态唯一性。
因为我们组件是做到复用的,所以就想到了使用 自定义 Hook 去拆解这一步业务逻辑。
业务代码实现
- 自定义Hook逻辑 将动态渲染的 FormItem 的校验逻辑抽离出来,将每个表单的校验状态和错误信息提取到一个公共的数据中
import { useState, useCallback }from 'react';
export function useValidator() {
// 定义错误状态的集合
const [status, setValidateStatus] = useState({});
// 定义错误信息的集合
const [errorMessage, setErrorMessage] = useState({});
// 当表单的FormItem的值发生变化,调用 valueChange 方法去修改FormItem对应的状态和错误信息
const valueChange = useCallback((name, value) => {
if(value) {
setValidateStatus({...status, [name]: ''})
setErrorMessage({...errorMessage, [name]: ''})
} else {
setValidateStatus({...status, [name]: 'error'})
setErrorMessage({...errorMessage, [name]: '请设置有效值'})
}
}, [])
// hook对外抛出状态和值改变的调用方法
return [status, errorMessage, valueChange];
}
- 组件引入自定义 hook
import { useValidator } from './hook'
export default (props: IProps) => {
const [form] = Form.useForm();
此处省略若干代码....
// 在组建顶层,调用最定义hook
const [status, errorMessage, valueChange] : any = useValidator();
.....
const fields = allFields
.filter(ele => names.includes(ele.name))
.map(field => {
const currentName = field.name;
const itemField = { ...field, disabled: readOnly || disabled };
const editableFieldChange = async value => {
// 使用受控组件的方式
onValueChange(currentName, value);
当值改变的时候调用hook的方法,去修改状态
valueChange(currentName, value)
};
return (
<FormItem
validateStatus={status[currentName]}
help={errorMessage[currentName]}
>
<EditableField
page={props?.page}
onChange={editableFieldChange}
field={itemField}
value={get(formData, currentName)}
/>
</FormItem>
);
});
}
自定义hook的注意事项
- 自定义 Hook 是一种自然遵循 Hook 设计的约定,而并不是 React 的特性。
- 自定义 Hook 必须以 “
use” 开头 - 在两个组件中使用相同的 Hook 不会共享 state。
自定义 Hook 是一种重用状态逻辑的机制(例如设置为订阅并存储当前值),所以每次使用自定义 Hook 时,其中的所有 state 和副作用都是完全隔离的。
- 每次调用 Hook,它都会获取独立的
state - 不要在循环、条件或者嵌套中使用,要在组件最顶层使用
结语
如果这篇文章帮到了你,欢迎点赞👍和关注⭐️。
文章如有错误之处,希望在评论区指正🙏🙏
欢迎关注我的微信公众号,一起交流技术,微信搜索 🔍 :「 五十年以后 」