Компонент ReactJS — Input ведет себя странно, когда он возвращается из функции

#javascript #reactjs

#javascript #reactjs

Вопрос:

Сценарий

Я объявил компонент react, который отображает простой тег ввода html.

 const MyComponent = (props) => (
  <input
    defaultValue="test"
    onChange={(e) => {
      props.setTitle(e.target.value);
    }}
  />
);
  

Затем я объявил функцию, которая принимает a setState в качестве параметра и возвращает этот компонент с setState внутренними входными onChange данными.

 const getComponent = (setTitle) => (props) => (
  <input
    defaultValue="test"
    onChange={(e) => {
      setTitle(e.target.value);
    }}
  />
);
  

Затем я вызвал свою функцию, чтобы получить компонент и отобразить его:

 const Root = () => {
  const [title, setTitle] = React.useState('');
  const Component = getComponent(setTitle);
  return (
    <div>
      <div>{title}</div>
      <Component />{' '}
    </div>
  );
};
  

Ожидаемый:
Входной элемент ведет себя нормально и изменяет свое значение

Реальность: ввод теряет фокус после каждого введенного символа и не сохраняет свое значение.

Вот простой пример ошибки: CodeSandbox

Комментарии:

1. Когда вы обновляете состояние компонента, он повторно отображается, что может привести к описываемому вами поведению

2. Когда я использую компонент напрямую, а не получаю его из функции GetComponent, он работает должным образом, даже если состояние изменяется. Я не понимаю, почему это не то же самое поведение, когда я получаю его из функции

Ответ №1:

Причина, по которой это происходит, заключается в том, что когда ваш код доходит до этой строки:

 const Component = getComponent(setTitle);
  

Это генерирует новую функцию (т. Е. Новый экземпляр), которая не отображается снова, а монтируется снова. Именно по этой причине вы не фокусируетесь на поле.

Вы никак не сможете заставить эту работу работать таким образом, она просто не предназначена для такой работы. Когда вы делаете это один раз при экспорте, тогда все в порядке, но каждый раз === новый экземпляр.

Если это всего лишь эксперимент, который вы пытаетесь, тогда все в порядке. Но нет причин не передавать setState его в качестве prop этому компоненту.

Комментарии:

1. я создаю компонент высокого порядка, который должен что-то сделать с setState, прежде чем передавать его компоненту.

2. Это недалеко от того, что такое компонент более высокого порядка, когда у вас есть функция, возвращающая компонент. Если бы вы переместили const Component = getComponent(setTitle); строку за пределы компонента, она не перемонтировала бы каждый рендеринг, но затем setTitle вышла бы за рамки, и у вас все еще осталась проблема.

3. При использовании HOC это обычно выполняется вне кода рендеринга компонента, т.Е. Когда вы создаете компонент с помощью HOC и либо сохраняете его внутри const, либо экспортируете из файла. Но поскольку ваш Root компонент время от времени обновляется в зависимости от его состояния, вы будете получать новый компонент каждый раз

Ответ №2:

Я нашел решение, которое позволяет мне использовать функцию и не позволять компоненту монтировать каждый раз.

Если вы поместите вызов функции внутри jsx, компонент не будет перемонтировать каждый рендеринг.

 const Root = () => {
  const [title, setTitle] = React.useState('');
  const Component = ;
  const someprops = {};
  return (
    <div>
      <div>{title}</div>
      {getComponent(setTitle)(someprops)}
    </div>
  );
};