У меня есть следующая структура:
FormEditor
- содержит несколько FieldEditor
FieldEditor
- редактирует поле формы и сохраняет различные значения об этом в своем состоянии
Когда кнопка нажата в FormEditor, я хочу иметь возможность собирать информацию о полях из всех FieldEditor
компонентов, информацию, которая находится в их состоянии, и иметь все это в FormEditor.
Я подумал о том, чтобы хранить информацию о полях за пределами FieldEditor
российского состояния и FormEditor
вместо этого переводить ее в состояние. Однако для этого потребуется FormEditor
прослушивать каждый из его FieldEditor
компонентов по мере их изменения и сохранять свою информацию в своем состоянии.
Разве я не могу просто получить доступ к состоянию детей? Это идеально?
javascript
reactjs
Моше Рева
источник
источник
FieldEditor
s отдельно, сохраните их состояние вFormEditor
хорошем звуке. Если это так, вашиFieldEditor
экземпляры будут отображаться на основеprops
переданного их редактором форм, а не ихstate
. Более сложным, но гибким способом было бы создать сериализатор, который проходит через любые дочерние элементы контейнера, находит всеFormEditor
экземпляры среди них и сериализует их в объект JSON. Объект JSON может быть необязательно вложенным (более одного уровня) на основе уровней вложенности экземпляров в редакторе форм.Ответы:
Если у вас уже есть обработчик onChange для отдельных FieldEditors, я не понимаю, почему вы не могли просто переместить состояние в компонент FormEditor и просто передать обратный вызов оттуда в FieldEditors, который обновит родительское состояние. Мне кажется, это более эффективный способ сделать это.
Возможно, что-то в этом роде:
Оригинал - версия с предварительным крючком:
Показать фрагмент кода
источник
myAPI.SaveStuff(this.state);
. Если вы укажете немного больше, может быть, я могу дать вам лучший ответ :)Непосредственно перед тем, как я подробно расскажу о том, как вы можете получить доступ к состоянию дочернего компонента, пожалуйста, прочитайте ответ Markus-ipse относительно лучшего решения для этого конкретного сценария.
Если вы действительно хотите получить доступ к состоянию дочерних компонентов, вы можете назначить свойство, вызываемое
ref
для каждого дочернего элемента . Теперь есть два способа реализации ссылок: использованиеReact.createRef()
и обратный вызов refs.С помощью
React.createRef()
В настоящее время это рекомендуемый способ использования ссылок с React 16.3 (дополнительную информацию см. В документации ). Если вы используете более раннюю версию, то смотрите ниже ссылки обратного вызова.
Вам нужно будет создать новую ссылку в конструкторе вашего родительского компонента, а затем назначить ее дочернему элементу через
ref
атрибут.Чтобы получить доступ к этому виду ссылки, вам необходимо использовать:
Это вернет экземпляр смонтированного компонента, так что вы сможете использовать его
currentFieldEditor1.state
для доступа к состоянию.Просто небольшое замечание, чтобы сказать, что если вы используете эти ссылки на узле DOM вместо компонента (например
<div ref={this.divRef} />
), тоthis.divRef.current
вернет базовый элемент DOM вместо экземпляра компонента.Обратный звонок
Это свойство принимает функцию обратного вызова, которой передается ссылка на присоединенный компонент. Этот обратный вызов выполняется сразу после монтирования или демонтажа компонента.
Например:
В этих примерах ссылка хранится на родительском компоненте. Чтобы вызвать этот компонент в своем коде, вы можете использовать:
а затем использовать,
this.fieldEditor1.state
чтобы получить состояние.Прежде всего, убедитесь, что ваш дочерний компонент отрисован, прежде чем пытаться получить к нему доступ ^ _ ^
Как и выше, если вы используете эти ссылки на узле DOM вместо компонента (например
<div ref={(divRef) => {this.myDiv = divRef;}} />
), тогдаthis.divRef
будет возвращаться базовый элемент DOM вместо экземпляра компонента.Дальнейшая информация
Если вы хотите узнать больше о недвижимости React, проверьте эту страницу на Facebook.
Обязательно прочитайте раздел « Не злоупотребляйте ссылками », в котором говорится, что вы не должны использовать ребенка,
state
чтобы «добиться успеха».Надеюсь, это поможет ^ _ ^
Редактировать: Добавлен
React.createRef()
метод для создания ссылок. Удален код ES5.источник
this.refs.yourComponentNameHere
. Я нашел это полезным для изменения состояния с помощью функций. Пример:this.refs.textInputField.clearInput();
props
иstate
. Однако они не должны быть вашей основной абстракцией для передачи данных через ваше приложение. По умолчанию используйте Поток данных Reactive и сохраняйтеref
s для вариантов использования, которые по своей природе не являются реактивными.connected
компонентом Redux ?Его 2020 и многие из вас приедут сюда в поисках аналогичного решения, но с Хуками (они великолепны!) И с новейшими подходами с точки зрения чистоты кода и синтаксиса.
Таким образом, как указывалось в предыдущих ответах, наилучший подход к решению этой проблемы состоит в том, чтобы удерживать состояние вне дочернего компонента
fieldEditor
. Вы можете сделать это несколькими способами.Наиболее «сложным» является глобальный контекст (состояние), к которому могут обращаться и изменять как родитель, так и потомки. Это отличное решение, когда компоненты очень глубоко в древовидной иерархии, и поэтому дорого отправлять реквизиты на каждом уровне.
В этом случае я думаю, что это того не стоит, и более простой подход принесет нам результаты, которых мы хотим, просто используя мощные
React.useState()
.Подход с хуком React.useState (), намного проще, чем с компонентами класса
Как уже было сказано, мы будем иметь дело с изменениями и будем хранить данные нашего дочернего компонента
fieldEditor
в нашем родителеfieldForm
. Для этого мы отправим ссылку на функцию, которая будет обрабатывать и применять изменения кfieldForm
состоянию, вы можете сделать это с помощью:Обратите внимание, что
React.useState({})
будет возвращен массив с позицией 0, являющейся значением, указанным при вызове (в данном случае пустым объектом), а позицией 1 будет ссылка на функцию, которая изменяет значение.Теперь, с дочерним компонентом,
FieldEditor
вам даже не нужно создавать функцию с оператором return, подойдет константа lean с функцией стрелки!Аааа, и все готово, не более того, только с этими двумя функциональными компонентами слизи у нас есть конечная цель - получить доступ к нашему дочернему
FieldEditor
значению и показать его в нашем родителе.Вы можете проверить принятый ответ 5 лет назад и посмотреть, как Hooks сделал код React более простым (на много!).
Надеюсь, мой ответ поможет вам узнать и понять больше о крючках, и если вы хотите проверить рабочий пример, вот он .
источник
Теперь вы можете получить доступ к состоянию InputField, которое является дочерним по отношению к FormEditor.
По сути, всякий раз, когда происходит изменение в состоянии поля ввода (дочернего), мы получаем значение из объекта события и затем передаем это значение в Parent, где устанавливается состояние в Parent.
При нажатии кнопки мы просто печатаем состояние полей ввода.
Ключевым моментом здесь является то, что мы используем реквизиты для получения идентификатора / значения поля ввода, а также для вызова функций, которые задаются как атрибуты поля ввода, в то время как мы генерируем многократно используемые дочерние поля ввода.
источник
Как и в предыдущих ответах, попробуйте переместить состояние в верхний компонент и изменить его с помощью обратных вызовов, передаваемых его дочерним элементам.
В случае, если вам действительно нужен доступ к дочернему состоянию, которое объявлено как функциональный компонент (хуки), вы можете объявить ref в родительском компоненте, а затем передать его как атрибут ref дочернему элементу, но вам нужно использовать React.forwardRef. а затем хук useImperativeHandle для объявления функции, которую вы можете вызвать в родительском компоненте.
Взгляните на следующий пример:
Тогда вы сможете получить myState в родительском компоненте, вызвав:
myRef.current.getMyState();
источник