Я представляю два разных способа визуализации компонента ввода;
function myComponent(){
const [st, setSt] = useState('');
return <div>
{Math.random()}
<input value = {st}
onChange = {e=>setSt(e.target.value)/>
</div>
function StateHelper() {
const [st, setSt] = useState("");
return { context: { st, setSt } };
}
function MyHelper(prop) {
const ActualComponent = prop.capture;
return <ActualComponent />;
}
function MyComponent() {
const { context } = StateHelper();
const capturedComponent = () => (
<input
value = {context.st}
onChange = {(e) => {
context.setSt(e.target.value);
}}
/>
);
return <MyHelper capture = {capturedComponent} />;
}
Кажется, я запутался в одной из основ.
Например, 1, когда я печатаю, я не теряю фокус на компоненте ввода.
Например, 2, на каждой набранной букве я теряю фокус.
В обоих этих примерах Math.random() изменяется, поэтому они оба перерисовываются.
Я не знаю, в чем разница и почему я продолжаю терять внимание, например. 2 ?
Я пытаюсь следовать, например. 2, так как это помогает мне лучше управлять своим кодом, но я не могу его понять. Что я не понимаю в повторном рендеринге компонентов реагирования и как это исправить?
Я проверил это (мне пришлось исправить некоторый синтаксис), и это работает, фокус не теряется. Я думаю, вы создали свой компонент внутри другого компонента. Кроме того, добавлять такой код очень неудобно, поскольку его невозможно скопировать.
Пожалуйста, также покажите, как вы используете эти компоненты – поскольку они называются myComponent
вместо MyComponent
, для начала вам придется пройти дополнительные этапы (вы не можете сделать <myComponent />
, поскольку JSX интерпретирует myComponent
как имя внутренний элемент).
принял к сведению, я обновляю код как можно скорее
Я пытаюсь добавить скрипку, чтобы воспроизвести проблему.
@AKX, я обновил код, добавив работоспособную скрипту, кажется, например. 2 вводил в заблуждение
@Конрад, кажется, мой например. 2 ввел в заблуждение, я добавил работоспособную скрипку
извините всех за неудобства, кажется, я допустил ошибку, приведя минимальный пример
Та же проблема stackoverflow.com/questions/59715158/…
Ваша const capturedComponent = () => (
— это внутренняя функция, идентичность которой меняется при каждом вызове объявляющего ее компонента.
Это заставляет React думать, что компонент не тот, который он рендерил в прошлый раз, поэтому он размонтирует старый и перемонтирует новый (даже если они могут быть идентичны на выходе), что, в свою очередь, приводит к потере фокуса на входной элемент.
Более подробную информацию см. в документации по правилу React ESlint для этой проблемы.
а что в примере 1? Почему мы не теряем фокус, даже если весь компонент перерисовывается?
Повторный рендеринг @BumbleBee не является проблемой. Перемонтирование есть. Компонент во втором примере уничтожается и создается заново каждый раз, когда вы нажимаете клавишу.
кажется, полезно почитать: ferreira.io/posts/re-mounting-vs-re-rendering
@AKX, в предоставленной вами ссылке упоминается решение не использовать запомненную функцию для захвата значения переменной, тогда я не понимаю, как зафиксировать значение переменной, когда вам нужно сказать, сохраняйте состояние на уровне страницы? Выше я не могу переместить StateHelper() за пределы <MyComponent/>, потому что хочу, чтобы состояние сохранялось в <MyComponent>. Есть ли у вас какие-либо предложения?
Вы переместите capturedComponent
наружу MyComponent
и передадите ему st
и setSt
в качестве реквизита (или используете API контекста React в более сложных случаях).
но в приведенном выше случае вы не можете этого сделать. Захваченный компонент имеет захваченные значения, и вам затем придется добавить логику в MyHelper и... ну, в общем, выполнить бурение пропеллеров.
Ваши примеры ни в коей мере не верны для React. Пожалуйста, переформатируйте это, чтобы они были последовательно, а не рядом.