Можно ли избежать повторного рендеринга всех входных данных при прохождении всего объекта? - PullRequest
0 голосов
/ 29 апреля 2020

У меня довольно много различных интерфейсов со многими свойствами, такими как

interface IEntity1 {
    a: string
    b: number
    c: string
    ....
}

Когда я хочу отредактировать объект (то есть создать измененную копию), я могу сделать

function Editor(props: {entity: IEntity1, setEntity(e: IEntity1) => void}) {
    const {entity, setEntity} = props;
    const [a, setA] = useState(entity.a);
    const [b, setB] = useState(entity.a);
    ....
    function handleOk() {
       setEntity({a, b, c, ...});
    }

    return <div>
       <input value={a} onChange={e => setA(e.target.value}/>
       <input value={''+b} onChange={e => setB(+e.target.value}/>
       <input value={c} onChange={e => setC(e.target.value}/>
       ...
       <button onClick={handleOk}>OK</button>
    </div>;
}

Это отлично работает, но довольно повторяющееся. Поэтому я создал «универсальный» компонент, который может обрабатывать числа, строки и другие входные данные. Используя его, я могу обрабатывать все поля в al oop, как

{fieldNames.map(f => <Edit value={entity[f]}
                       onChange={newValue => setEntity({...entity}, {[f]: newValue})}/>)}

. Я могу с легкостью генерировать все необходимые метаданные (выше для простоты просто fieldNames: string[]). Я могу сделать еще лучше с

{fieldsMetadata.map(f => <Edit2 entity={entity} field={f}/>)}

, где Edit2 является «более умным» компонентом. Что меня беспокоит, так это то, что все мои правки повторно отображаются при любом изменении. Это может быть преждевременной оптимизацией, но, учитывая, что я хочу использовать этот компонент много раз на многих страницах, это может быть серьезной проблемой.

Поэтому я спрашиваю, возможно ли написать такой компонент без его повторного рендеринга каждый раз, или есть что-то, имеющее отношение к производительности, что Я скучаю?

1 Ответ

0 голосов
/ 29 апреля 2020

Проблема с повторным рендерингом вашего компонента заключается в том, что при передаче функции встроенной стрелки, которая создается заново при каждом рендеринге

Как только вы ее избежите, вы можете реализовать каждый компонент Edit с React.memo или PureComponent в зависимости от от того, реализуете ли вы его как функциональный компонент или класс

const onChange= useCallback((name, value) => {
     setEntity(prev => ({...prev, [name]: value}));
}, []);
 ...
{fieldNames.map(f => <Edit name={f} value={entity[f]}
                       onChange={onChange}/>)}

, а компонент редактирования будет выглядеть так:

const Edit = (props) => {
    const {value, name, setEntity} = props;
    const handleChange = (e) => {
         const newValue = e.target.value;
         onChange(name, newValue);
    }

    return <input value={value} name={name} onChange={handleChange} />

}

export default React.memo(Edit)

PS Убедитесь, что вы правильно объединяете состояние с setEntity

...