Как повторно отрендерить только TextInput, который изменился в компоненте, который отображает 3 TextInput, которые имеют одинаковое состояние (длина массива 3 строки)? - PullRequest
0 голосов
/ 27 мая 2019

У меня есть следующая структура компонента, которая отображает компонент 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, чтобы они могли вызывать изменение дескриптора с соответствующим индексом. Это плохая практика как-то?

...