React Context перерисовка всех дочерних элементов
Реализован компонент формы
Подключение:
import React from 'react';
import { Form, Input, Button } from './../Design/Components';
interface PropsTypes {
...
}
const AddGroupModal = (props: PropsTypes): JSX.Element => {
const formSubmit = () => {
}
return (
<Form
initialValues={{
title: '',
name: ''
}}
onSubmit={formSubmit}
>
<Form.Field
name="title"
>
<Input placeholder="Наименование" />
</Form.Field>
<Form.Field
name="name"
>
<Input placeholder="Еще поле" />
</Form.Field>
<Button>Сохранить</Button>
</Form>
)
}
export default AddGroupModal;
Компонент Form
import React, { useState } from 'react';
import { FormField } from './FormField';
import { FormProps, FormContextT } from './../../../types/form';
import './style.scss';
export const FormContext = React.createContext<FormContextT>({
formData: {},
handleFieldChange: () => {}
});
export const Form = (props: FormProps): JSX.Element => {
const { children, initialValues, className, onSubmit } = props;
const [ formData, setFormData] = useState(initialValues);
const handlerSubmit = (e: React.SyntheticEvent): void => {
e.preventDefault();
onSubmit();
}
const validate = () => {
}
const handleFieldChange = (name: string, value: string) => {
setFormData({
...formData,
[name]: value
});
}
const context:FormContextT = {
formData,
handleFieldChange
}
return (
<FormContext.Provider value={context}>
<form
className={`form${className ? ' ' + className : ''}`}
onSubmit={handlerSubmit}
>
{children}
</form>
</FormContext.Provider>
)
}
Form.Field = FormField
Компонент FormField
import React, { useContext } from 'react';
import { FormContext } from './Form';
import { FormFieldProps } from './../../../types/form';
export const FormField = (props: FormFieldProps): JSX.Element => {
const { name, children } = props;
const formContext = useContext(FormContext);
const { formData, handleFieldChange } = formContext;
const fieldChange = (e: React.ChangeEvent<HTMLInputElement>) => {
handleFieldChange(name, e.target.value);
if('onChange' in children.props) {
children.props.onChange(e);
}
}
console.log('re-render: ' + name);
return (
React.cloneElement(children, {
name,
onChange: fieldChange,
value: formData[name]
})
);
};
Компонент Input
export const Input = (props: PropsTypes) => {
const { className, value, name, placeholder, disabled, onChange, type = 'text' } = props;
console.log('re-render-input: ' + name);
return (
<input
type={type}
name={name!}
value={value!}
placeholder={placeholder!}
disabled={disabled!}
className={`input${className ? ' ' + className : ''}`}
onChange={onChange!}
/>
)
}
Все значения полей формы записываются в объект formData в формате {поле: значение} в компоненте Form и через React Context передаются в FormField. Проблема в том, что при перезаписи значения поля обновляется formData в родительском компоненте, и перерендериваются все дочерние FormField. Подскажите, как сделать, чтобы перерендеривался только тот дочерний, который был изменен. Пытался использовать хук UseMemo, но не смог его правильно применить.