Реактивная маршрутизация приводит к потере фокуса входами - PullRequest
1 голос
/ 09 апреля 2020

У меня есть приложение с компонентом, в котором есть входы. Когда пользователь изменяет входные данные, я хочу обновить строку запроса в URL, чтобы отразить новое состояние. Я достигаю этого, обнаруживая разницу между текущими значениями location.search и строкой запроса, которую мое состояние будет генерировать . Если есть разница, я возвращаю <Redirect> компонент с аргументами запроса, отражающими новое состояние.

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

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

Я уменьшил проблему до минимального приложения с https://codesandbox.io/s/github/TrevorMills/react-routing-conundrum. Проблема проявляется как на функциональных компонентах, так и на React.Component классах.

Мой механизм кажется мне взломанным. Мой вопрос к экспертам React есть, я что-то пропустил? Есть ли лучший способ получить состояние в параметрах запроса местоположения, чем <Redirect>? Я попытался добавить key к своим данным, но это не имело значения. Если мой механизм выглядит как le git, есть ли способ применить его к приложению в целом в компоненте более высокого порядка?

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 09 апреля 2020

Поскольку вы использовали перенаправление, при каждом изменении входного значения рендеринг компонента переключается между возвращаемым значением и перенаправлением, в результате чего все компоненты перемонтируются вместо повторного рендеринга. Это приводит к тому, что поле ввода теряет фокус.

Избегайте использования <Redirect /> и используйте history.replace после обновления состояния.

Вместо выполнения функции history.replace в onChangeText вы можете написать useEffect, например, так.

useEffect(() => {
    props.history.replace(props.location.pathname + "?" + qs.stringify(state));
  }, [state]);

Обновленный рабочий пример приведен здесь:

https://codesandbox.io/s/cocky-swirles-kcqwo?file= / src / App. js

1 голос
/ 09 апреля 2020

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

Главное, что я сделал, - удалил дублирование состояний. Вместо дублирования состояния от маршрута до компонента, я просто заставил компонент использовать параметры запроса непосредственно в качестве состояния. И затем я заставил функцию updateState обновлять параметры запроса, используя props.history.replace. Именно так React Router обеспечивает императивную навигацию.

Надеюсь, это поможет!

https://codesandbox.io/s/great-williamson-0pxyb

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...