WedX - журнал о программировании и компьютерных науках

Реагировать на крючки useState — ввод текста теряет фокус при вводе, если форма передается через реквизиты

У меня есть повторно используемый компонент <Layout />, который позволяет мне передавать пользовательские компоненты в свойства content и sidebar.

В одном случае я помещаю поле ввода в содержимое, которое является управляемым компонентом и использует useState() для обработки данных.

Однако я обнаружил, что моя клавиатура теряет фокус всякий раз, когда я ввожу ввод. Похоже, вся форма перерисовывается, и я не могу остановить это.

Это было нормально, когда мой код был полностью встроенным, но после его рефакторинга для использования компонента <Layout /> он имеет некоторые странные эффекты.

  • Я не хочу использовать какие-либо дополнительные библиотеки, кроме основной React 16.x.
  • Я пробовал использовать useCallback(), ключи, имена, идентификаторы, ссылки - все безрезультатно
  • Я переместил функции обратного вызова за пределы области действия и передал значения в соответствии с этим ответом, но проблема не устранена.

import React, { useState } from 'react';

function Layout({ content: Content, sidebar: Sidebar }) {
  return (
    <>
      <div>
        <Content />
      </div>
      <div>
        <Sidebar />
      </div>
    </>
  );
}

function Page() {
  const [value, setValue] = useState('');
  return (
    <>
      <Layout
        content={() => (
          <input
            value={value}
            onChange={(event) => setValue(event.target.value)}
          />
        )}
        sidebar={() => (
          <p>Lorem ipsum...</p>
        )}
      />
    </>
  );
}

export default Page;
13.05.2020

  • Надеюсь, это полезный пост SO в стиле вопросов и ответов для людей. Это может быть слишком специфично, я не уверен, но это определенно поставило меня в тупик в проекте, над которым я работаю, и подумал, что это может помочь кому-то! :) 13.05.2020
  • Попробуйте по адресу: repl.it/repls/AbleFrugalParticles. 13.05.2020

Ответы:


1

Ваша проблема в том, что вы определяете анонимные функции и рассматриваете их как компоненты React, что хорошо во многих случаях, но здесь React теряет понимание основного содержимого этих функций. Это означает, что даже добавление ссылок или ключей на вход ничего не даст, так как внешняя область видимости каждый раз просто видит совершенно новую функцию.

Задумайтесь на секунду: вместо того, чтобы писать <Content />, вы пишете <>{Content()}</>

Это даст тот же результат, но показывает, что каждый раз, когда Layout отображается, он имеет совершенно другое представление о том, каковы его свойства, и, таким образом, каждый раз отображает все заново. Поскольку ввод быстро заменяется новым, но другим вводом, браузер теряет фокус в поле. Но это также может вызвать массу других проблем.

Вместо этого замените <Content /> на {content} и не пропускайте анонимную функцию — вместо этого просто передайте необработанный JSX как есть, и он больше не будет повторно отображать дочерние элементы.

import React, { useState } from 'react';

function Layout({ content, sidebar }) {
  return (
    <>
      <div>
        {content}
      </div>
      <div>
        {sidebar}
      </div>
    </>
  );
}

function Page() {
  const [value, setValue] = useState('');
  return (
    <>
      <Layout
        content={(
          <input
            value={value}
            onChange={(event) => setValue(event.target.value)}
          />
        )}
        sidebar={(
          <p>Lorem ipsum...</p>
        )}
      />
    </>
  );
}

export default Page;
13.05.2020

2

Проблема в том, что когда Content визуализируется как компонент реакции внутри Layout, каждый раз, когда Page перерисовывается, создается новый экземпляр функций content и sidebar, из-за этого реакция перемонтирует компонент по мере изменения ссылок на функции, потому что функции воссоздаются при каждом рендеринге внутри компонента реакции, и поэтому фокус ввода теряется.

Вы можете использовать компоненты content и sidebar в качестве реквизита рендеринга. Свойство рендеринга — это свойство функции, которое компонент использует, чтобы знать, что отображать. Вызовите функции внутри Layout для рендеринга Content и Sidebar.

function Layout({ content: Content, sidebar: Sidebar }) {
  return (
    <>
      <div>{Content()}</div>
      <div>{Sidebar()}</div>
    </>
  );
}

function Page() {
  const [value, setValue] = useState("");

  return (
    <>
      <Layout
        content={() => (
          <input
            value={value}
            onChange={event => setValue(event.target.value)}
          />
        )}
        sidebar={() => <p>Lorem ipsum...</p>}
      />
    </>
  );
}
13.05.2020
Новые материалы

Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

Объяснение документов 02: BERT
BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

Как проанализировать работу вашего классификатора?
Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


Для любых предложений по сайту: [email protected]