单个组件输入在更改一个输入值时始终重新渲染

问题描述 投票:0回答:1

我面临的问题与 React 如何处理状态更新和重新渲染有关。当您更改表单中某一字段(姓名、电子邮件或电话)的值时,所有三个输入组件都会重新呈现,因为它们都依赖于相同的 formData 状态。当状态改变时,React 会重新渲染整个组件,这就是为什么所有输入都会重新渲染,即使只有一个字段的值发生了变化。

在下面,如果更改名称的值,所有 3 个输入组件都将重新渲染。

const [formData, setFormData] = useState({ name: '', email: '', phone: '';

<FormInput
                    label="Name"
                    placeholder="Enter name"
                    id="name"
                    value={formData.name}
                    onChange={handleChange}
                />

                <FormInput
                    label="Email"
                    placeholder="Enter email"
                    type='email'
                    id="email"
                    value={formData.email}
                    onChange={handleChange}
                />

                <FormInput
                    label="Phone"
                    placeholder="Enter phone"
                    type='number'
                    id="phone"
                    value={formData.phone}
                    onChange={handleChange}
                />

表单输入.jsx

import { forwardRef} from "react";
import { cx } from "../../utils/helper";

export const commonInputCss = "w-full border border-neutral-300 rounded-xl p-4 outline-none text-text-700 placeholder:text-text-disabled bg-white disabled:bg-text-disabled disabled:cursor-not-allowed disabled:opacity-50 disabled:placeholder:text-main-black";

const FormInput = forwardRef(({
    label, type = "text", id, inputCss, ...props
}, ref) => {

    return (
        <div className={cx("relative flex flex-col gap-y-1")}>
            {label && (
                <label htmlFor={id} className={cx(
                    "text-text-700 text-sm text-medium",
                    labelCss
                )}>
                    {label}
                </label>
            )}

            <input
                type={type}
                name={id}
                id={id}
                ref={ref}
                {...props}
                className={cx(
                    commonInputCss,
                    inputCss,
                )}
            />
        </div>
    );
});

export default FormInput;

但是,我们需要重新渲染所有属性来更改一个属性值吗?

javascript reactjs
1个回答
0
投票
  1. 我们可以对所有输入使用不同的状态,这将减少更多的代码行。 (不推荐)
  2. 我们可以对所有输入使用 useRef 钩子,这也可以减少更多行代码。 (不推荐)
  3. 您可以使用 memo hook 来记住输入值。
  4. 您可以使用react-hook-from包。其中,像 useRef hook 一样遵循,但不需要编写多行代码。等等

使用示例React Hook Form

import React, { useState } from 'react';
import FormInput from '../../shared/forms/FormInput';
import { Controller, useForm } from 'react-hook-form';

const AddSellerModal = ({ isOpen, closeModal }) => {

    const { control, handleSubmit, reset } = useForm({ 
        defaultValues: { name: '', email: '', email: '', phone: '' } 
    });

    return (
        <>
                <div className='my-10 space-y-5'>
                    <Controller
                        name="name"
                        control={control}
                        render={({ field }) => (
                            <FormInput
                                label="Shop Name"
                                placeholder="Enter shop name"
                                id="name"
                                {...field}
                            />
                        )}
                    />

                    <Controller
                        name="location"
                        control={control}
                        render={({ field }) => (
                            <FormInput
                                label="Location"
                                placeholder="Enter location"
                                id="location"
                                {...field}
                            />
                        )}
                    />

                    <Controller
                        name="email"
                        control={control}
                        render={({ field }) => (
                            <FormInput
                                label="Email"
                                placeholder="Enter email"
                                id="email"
                                type='email'
                                {...field}
                            />
                        )}
                    />

                    <Controller
                        name="phone"
                        control={control}
                        render={({ field }) => (
                            <FormInput
                                label="Phone"
                                placeholder="Enter phone"
                                id="phone"
                                type='number'
                                {...field}
                            />
                        )}
                    />
                </div>
            </CustomContainerModal>
        </>

    );
};

export default AddSellerModal;
© www.soinside.com 2019 - 2024. All rights reserved.