react 简单demo -了解其渲染

文章介绍了如何使用Reacthooks实现自定义时间组件,通过useGetTime展示当前时间并进行性能优化。同时对比了受控组件和非受控组件的概念、使用方法以及watch和ProFormDependency在表单联动中的应用,讨论了渲染优化策略。
摘要由CSDN通过智能技术生成

这些是函数式写法,类写法参考我的其他文章,一些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、表单联动渲染

// 后续更新,渲染及性能优化

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是React Flow的一个基本示例,该示例使用自定义节点和连线样式,以及可拖动的节点和连线。你可以根据自己的需要进行修改和扩展。 ```jsx import React, { useState } from 'react'; import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls, Background, } from 'react-flow-renderer'; const initialElements = [ { id: '1', type: 'input', data: { label: 'Input Node' }, position: { x: 250, y: 5 } }, { id: '2', type: 'default', data: { label: 'Node 2' }, position: { x: 100, y: 100 } }, { id: '3', type: 'default', data: { label: 'Node 3' }, position: { x: 400, y: 100 } }, { id: '4', type: 'output', data: { label: 'Output Node' }, position: { x: 250, y: 200 } }, { id: 'e1-2', source: '1', target: '2', animated: true }, { id: 'e2-3', source: '2', target: '3', animated: true }, { id: 'e3-4', source: '3', target: '4', animated: true }, ]; const nodeTypes = { input: ({ data }) => ( <div className="node-input"> {data.label} </div> ), default: ({ data }) => ( <div className="node-default"> {data.label} </div> ), output: ({ data }) => ( <div className="node-output"> {data.label} </div> ), }; const App = () => { const [elements, setElements] = useState(initialElements); const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els)); const onConnect = (params) => setElements((els) => addEdge(params, els)); return ( <ReactFlowProvider> <div className="react-flow-wrapper"> <ReactFlow elements={elements} onElementsRemove={onElementsRemove} onConnect={onConnect} nodeTypes={nodeTypes} snapToGrid={true} snapGrid={[15, 15]} > <Controls /> <Background color="#888" gap={16} /> </ReactFlow> </div> </ReactFlowProvider> ); }; export default App; ``` 在上面的示例中,我们定义了一个最初包含四个节点和三个连接的元素数组。我们还定义了三种节点类型,分别是输入节点、默认节点和输出节点。 在ReactFlow组件中,我们将元素和节点类型传递给它,并指定了一些其他属性,如onElementsRemove和onConnect,用于删除和添加元素,以及snapToGrid和snapGrid,用于将节点对齐到网格上。 最后,我们使用ReactFlowProvider包装ReactFlow组件,以便在整个应用程序中共享ReactFlow的状态和功能。 如果你想要一个更复杂的示例,可以访问React Flow的官方网站,那里有许多其他示例和文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值