У меня есть следующая структура компонента, которая отображает компонент 3 TextInput's
:
Моя цель - перерисовать только TextInput
, который был изменен.
Пример для CodeSandbox:
https://wc3nr.codesandbox.io/
App.js (родительский компонент)
- Этот компонент должен обрабатывать все
state
и логику для обновления state
.
- Используется useCallback , чтобы функция
handleChange
всегда была одинаковой при рендеринге. В противном случае он будет меняться при каждом рендеринге и перерисовывать каждый ввод из-за этого изменения.
function App() {
console.log("Rendering App...");
const [inputValues, setInputValues] = useState(["", "", ""]);
const handleChange = useCallback((newValue, index) => {
setInputValues(prevState => {
const aux = Array.from(prevState);
aux[index] = newValue;
return aux;
});
}, []);
return <Description values={inputValues} handleChange={handleChange} />;
}
Description.js (рендеринг 3 TextInput's)
- Он в основном отображает массив
state
и отображает 1 вход для каждого значения.
import React from "react";
import TextInput from "./TextInput";
function Description(props) {
console.log("Rendering Description...");
const inputItems = props.values.map((item, index) => (
<div key={index}>
<div>Input {index + 1}</div>
<TextInput value={item} handleChange={props.handleChange} index={index} />
</div>
));
return <React.Fragment>{inputItems}</React.Fragment>;
}
TextInput.js (отображает базовый тип ввода = 'text')
- Он использует React.memo, чтобы избежать повторного рендеринга, если значение этого конкретного входа не изменилось (то есть только вход, который был изменен, должен повторно выполнить рендеринг).
import React from "react";
const TextInput = React.memo(function TextInput(props) {
console.log("Rendering TextInput..." + props.index);
return (
<input
type="text"
value={props.value}
onChange={event => props.handleChange(event.target.value, props.index)}
/>
);
// });
ВОПРОС
Работает как задумано. Но я чувствую, что общая структура стала немного "хакерской". И я хочу знать, есть ли лучший способ добиться этого или есть ли что-то, что я мог бы сделать, чтобы улучшить свой код и сделать его более понятным?
Обратите внимание, что в Description.js мне нужно было создать index prop
(реквизит с именем 'index') для передачи в TextInput, чтобы они могли вызывать изменение дескриптора с соответствующим индексом. Это плохая практика как-то?