这些是函数式写法,类写法参考我的其他文章,一些demo涉及React渲染及性能优化
显示时间
自定义hooks
使用定时器、生命周期、通过状态渲染更新
// hooks 文件
import { useEffect, useState } from 'react'
function getDate() {
let date = new Date();
let year = date.getFullYear()
let hour = date.getHours();
let minutes = date.getMinutes();
let second = date.getSeconds();
let time = `${year ?? '2024'}-${hour}:${minutes}:${second}` as string;
return time;
}
export function UseGetTime() {
const [time, setTime] = useState<string>('');
useEffect(() => {
setTime(getDate())
return () => {
clearInterval(timerId);
}
}, [time]);
let timerId = setInterval(() => {
setTime(getDate());
}, 1000);
return { getTime: time };
};
// time 文件
import React from 'react'
import { UseGetTime } from '../hooks/time'
const Time: React.FC = () => {
const { getTime } = UseGetTime();
return (<>{getTime}</>)
}
export default Time;
表单提交
import React from "react";
import { Form, Input, Button } from 'antd'
const FormDemo: React.FC = () => {
const [form] = Form.useForm();
const userName = Form.useWatch('username', form);
const onClick = () => {
console.log('提交内容', userName)
}
return (
<Form form={form}>
<Form.Item name={'username'}>
<Input style={{ width: 160 }} placeholder={'请输入录入项'}></Input>
</Form.Item>
<Form.Item>
<Button onClick={onClick} type="primary">提交</Button>
</Form.Item>
</Form>
)
};
export default FormDemo;
表单受控组件与非受控组件
受控组件
概念:由state状态值,交给react渲染机制控值,属于受控组件
机制:state存值,用户输入 =》onChange触发 =》set值 =》引起状态改变react重新渲染
注意:这边用Form和Form.item包裹并没有什么作用,因表单项无设定name值,无法获得表单值 ,但若设定name值反而导致受控组件失效交于form表单控制
import React, { InputHTMLAttributes, useCallback, useState } from "react";
import { Form, Input, Button, Select } from 'antd'
const FormDemo: React.FC = () => {
type ValueType = InputHTMLAttributes<HTMLInputElement>['value'] | bigint;
const [value, setValue] = useState<ValueType | string>();
const [form] = Form.useForm();
const onClick = () => {
console.log('提交内容', value)
}
const onChange = (_: string, event: Record<string, any>) => {
setValue(event.label); // 此用state,设置了简易的表单联动
}
const onchangeIn = (event: any) => {
setValue(event.target.value);
};
return (
<Form form={form}>
<Form.Item >
<Select showSearch placeholder="请选择" onChange={onChange} options={
[{
value: '01',
label: '男'
},
{
value: '02',
label: '女'
}
]
}></Select>
</Form.Item>
<Form.Item>
<Input value={value} style={{ width: 160 }} onChange={onchangeIn} placeholder={'请输入录入项'}></Input>
</Form.Item>
<Form.Item>
<Button onClick={onClick} type="primary">提交</Button>
</Form.Item>
</Form>
)
};
export default FormDemo;
非受控组件
概念:通过default设置默认值,由用户输入,通过dom来操作值,并不依赖react,属于非受控组件
机制:用户输入=》更新值
注意: 此时给表单项设置name值,交予表单控值,再给表单项设置value是无效的
import React, { InputHTMLAttributes, useCallback, useState } from "react";
import { Form, Input, Button, Select } from 'antd'
const FormDemo: React.FC = () => {
const [form] = Form.useForm();
const userName = Form.useWatch('username', form);
const getFormValues = form.getFieldsValue();
console.log('userName', userName);
console.log('getFormValues', getFormValues);
const onClick = () => {
console.log('提交内容', userName)
}
const onChange = (_: string, event: Record<string, any>) => {
// 赋值
}
const onchangeIn = (event: any) => {
// 赋值
};
return (
<Form form={form}>
<Form.Item name="category">
<Select showSearch placeholder="请选择" onChange={onChange} options={
[{
value: '01',
label: '男'
},
{
value: '02',
label: '女'
}
]
}></Select>
</Form.Item>
<Form.Item name="username">
<Input defaultValue={'男'} style={{ width: 160 }} onChange={onchangeIn} placeholder={'请输入录入项'}></Input>
</Form.Item>
<Form.Item>
<Button onClick={onClick} type="primary">提交</Button>
</Form.Item>
</Form>
)
};
export default FormDemo;
watch和 ProFormDependency 哪个好用?
来源:
watch 来源 Ant Plus 5 (antx)
ProFormDependency 来源 ProComponents
详解:
watch
首先,为什么这用watch而不是useWatch? 是因为useWatch本身也是由state构成,因此当局部表单更新,会导致整个组件重新渲染,造成不必要的性能消耗,如:表单实时输入获得数据,或频繁应用值
import React from "react";
import { Form, Input, Select } from 'antd'
const FormApply: React.FC = () => {
const [form] = Form.useForm();
const selectForm = Form.useWatch('select', form);
const inputForm = Form.useWatch('input', form);
const options = [{ value: '01', label: '男' }, { value: '02', label: '女' }];
console.log('form', form.getFieldsValue());
console.log('整个组件渲染...')
const onSelChange = () => {
console.log('selectForm', selectForm);
};
const onInChange = () => {
console.log('inputForm', inputForm);
console.log('form', form.getFieldsValue());
};
return (
<Form form={form}>
<Form.Item name={'select'}>
<Select options={options} onChange={onSelChange} />
</Form.Item>
<Form.Item name='input' >
<Input onChange={onInChange} />
</Form.Item>
</Form>
)
};
export default FormApply
这时可以使用 watch 来避免性能消耗,达成局部更新,也就是说按需更新渲染
如下:
由图可知,并没有输出: 整个组件渲染…
import React, { ReactNode } from "react";
import { Form } from 'antd'
import { Input, Select, Watch } from 'antx'
const FormApply: React.FC = () => {
const [form] = Form.useForm();
// const selectForm = Form.useWatch('select', form);
// const inputForm = Form.useWatch('input', form);
const options = [{ value: '01', label: '男' }, { value: '02', label: '女' }];
console.log('form', form.getFieldsValue());
console.log('整个组件渲染...')
const onSelChange = () => {
// console.log('selectForm', selectForm);
};
function fun<T>(a: T) {
return a
}
const onInChange = () => {
// console.log('inputForm', inputForm);
console.log('form', form.getFieldsValue());
};
return (
<Form form={form}>
<Form.Item>
<Select name={'select'} options={options} onChange={onSelChange} />
<Watch name={'select'} >
{(watchVale): ReactNode => {
console.log('watchVale...', watchVale);
return
}}
</Watch>
</Form.Item>
<Form.Item name='input' >
<Input onChange={onInChange} />
</Form.Item>
</Form>
)
};
export default FormApply
扩展知识
难道用watch 替用useWatch,那完全可作到局部刷新的效果吗? 并不完全是,想想react渲染机制,通过state触发更新,useWatch 本身由state构成,那么我若在watch组件中,绑定useWatch呢 ~.~ ,想像下,是不是又触发了?
以下俩例子,watch结合useWatch触发整体组件的渲染
watch组件绑定useWatch
注意:useWatch通过name绑定,当把name或useWatch卸绑,没有state并不触发全局组件渲染
import React, { ReactNode } from "react";
import { Form } from 'antd'
import { Select, Watch } from 'antx'
const FormApply: React.FC = () => {
const [form] = Form.useForm();
const useModeForm = Form.useWatch('useMode', form);
console.log('form', form.getFieldsValue());
console.log('整个组件渲染...')
console.log('useModeForm', useModeForm);
return (
<Form form={form}>
<Form.Item>
<Select name={'useMode'} style={{ width: '200px' }} options={[{ value: 'select', label: '选项框' }, { value: 'text', label: '文本项' }]} />
<Watch name={'useMode'} >
{(watchVale): ReactNode => {
console.log('watchVale', watchVale)
return
}}
</Watch>
</Form.Item>
</Form>
)
};
export default FormApply
watch组件通过依赖动态表单联动
import React, { ReactNode } from "react";
import { Form } from 'antd'
import { Input, Select, Watch } from 'antx'
const FormApply: React.FC = () => {
const [form] = Form.useForm();
const selectForm = Form.useWatch('selectForm', form);
const inForm = Form.useWatch('inputForm', form)
const options = [{ value: '01', label: '男' }, { value: '02', label: '女' }];
console.log('form', form.getFieldsValue());
console.log('整个组件渲染...')
const onSelChange = () => {
console.log('selectForm', selectForm);
console.log('form', form.getFieldsValue());
};
const onInChange = () => {
console.log('inputForm', inForm);
};
return (
<Form form={form}>
<Form.Item>
<Select name={'useMode'} style={{ width: '200px' }} options={[{ value: 'select', label: '选项框' }, { value: 'text', label: '文本项' }]} />
<Watch name={'useMode'} >
{(watchVale): ReactNode => {
if (!watchVale) return null;
return (watchVale === 'select') ? <Select name={'selectForm'} options={options} onChange={onSelChange} /> : <Input name={'inputForm'} onChange={onInChange} />
}}
</Watch>
</Form.Item>
</Form>
)
};
export default FormApply
结论:这块用watch替用useWatch主要作用是卸掉绑定,防止state触发渲染,并不是说watch本身它有避掉state的功能!它只是某种场景的需要,提供的一种优化方案
ProFormDependency
如图:表单联动,选择文本项,当输入内容后,并没有触发整组件刷新渲染
import React, { ReactNode } from "react";
import { Form } from 'antd'
import { ProForm, ProFormDependency, ProFormSelect, ProFormText } from '@ant-design/pro-components'
const FormApply: React.FC = () => {
const [form] = Form.useForm();
const textForm = Form.useWatch('text', form);
console.log('form', form.getFieldsValue());
console.log('整个组件渲染...');
console.log('textValue', textForm);
return (
<ProForm>
<ProFormSelect name='useMode' allowClear options={[{ value: 'select', label: '选项框' }, { value: 'text', label: '文本项' }]} />
<ProFormDependency name={['useMode']} >
{({ useMode }) => {
if (!useMode) return null;
return (
(useMode === 'select') ?
<ProFormSelect name='select' label={'请选择性别'} options={[{
value: '01',
label: '男'
},
{
value: '02',
label: '女'
}
]} /> : <ProFormText name='text' label={'请录入性别'} />
)
}}
</ProFormDependency>
</ProForm>
)
};
export default FormApply
// 待更新补充 近期更新内容:1、useWatch和 form.getFieldsValue ,useWatch某些场景有延迟效果? 2、ProFormDependency和useWatch具体区别点,场景扩展
区别:
相同点: 1、都能局部渲染刷新,并不引起整个组件渲染 2、都有依赖值可作表单联动
不同点: 1、watch需要避免绑定useWach
场景:
1、需要实时获得表单值,但不想引起全局组件渲染render
2、表单联动渲染
// 后续更新,渲染及性能优化