Здесь есть три ответа, в зависимости от версии React, с которой вы (вынуждены) работать (ing), и от того, хотите ли вы использовать хуки.
Перво-наперво:
Важно понимать, как работает React, чтобы вы могли делать все правильно (protip: это супер полезно пройти учебное упражнение React на веб-сайте React. Оно хорошо написано и охватывает все основы так, как на самом деле объясняется, как это сделать. вещи). «Правильно» здесь означает, что вы пишете интерфейс приложения, который отображается в браузере; вся работа с интерфейсом происходит в React, а не в «том, к чему вы привыкли, когда пишете веб-страницу» (именно поэтому приложения React являются «приложениями», а не «веб-страницами»).
Приложения React отображаются на основе двух вещей:
- свойства компонента, объявленные любым родительским объектом, создают экземпляр этого компонента, который родитель может изменять на протяжении всего своего жизненного цикла, и
- собственное внутреннее состояние компонента, которое он может изменять в течение всего своего жизненного цикла.
То, что вы явно не делаете при использовании React, - это генерирование HTML-элементов, а затем их использование: когда вы говорите React использовать <input>
, например, вы не создаете HTML-элемент ввода, вы говорите React создать входной объект React. что происходит с визуализацией в качестве входного элемента HTML, и чье событие обработки выглядит на, но не контролируется , входные событиями HTML элемента.
При использовании React вы создаете элементы пользовательского интерфейса приложения, которые предоставляют пользователю (часто манипулируемые) данные, когда взаимодействие с пользователем изменяет состояние компонента, что может привести к повторному отображению части интерфейса вашего приложения, чтобы отразить новое состояние. В этой модели состояние всегда является окончательным авторитетом, а не «какой бы библиотекой пользовательского интерфейса ни использовался для его визуализации», а в Интернете это DOM браузера. DOM - это почти запоздалая мысль в этой модели программирования: это просто конкретная среда пользовательского интерфейса, которую использует React.
Так что в случае элемента ввода логика:
- Вы вводите элемент ввода,
- с вашим элементом ввода пока ничего не происходит, событие было перехвачено React и немедленно уничтожено ,
- React перенаправляет событие в функцию, которую вы настроили для обработки событий,
- эта функция может запланировать обновление состояния,
- если это произойдет, React выполнит это обновление состояния (асинхронно!) и вызовет
render
вызов после обновления, но только если обновление состояния изменило состояние.
- только после этого рендеринга пользовательский интерфейс покажет, что вы «набрали букву».
Все это происходит за считанные миллисекунды, если не меньше, поэтому похоже, что вы вводили элемент ввода точно так же, как вы привыкли к тому, что «просто используете элемент ввода на странице», но это совершенно не то, что получилось.
Итак, с учетом сказанного о том, как получить значения из элементов в React:
Реагируйте 15 и ниже, с ES5
Чтобы сделать все правильно, ваш компонент имеет значение состояния, которое отображается через поле ввода, и мы можем обновить его, заставив этот элемент пользовательского интерфейса отправлять события изменения обратно в компонент:
var Component = React.createClass({
getInitialState: function() {
return {
inputValue: ''
};
},
render: function() {
return (
//...
<input value={this.state.inputValue} onChange={this.updateInputValue}/>
//...
);
},
updateInputValue: function(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
Таким образом , мы говорим Реагировать использовать updateInputValue
функцию для обработки взаимодействия с пользователем, использование setState
для планирования состояния обновления, а также тот факт , что render
краны в this.state.inputValue
означает , что , когда он повторно выводит после обновления состояния, пользователь увидит текст обновления , основываясь на том, что они ввели.
приложение на основе комментариев
Учитывая, что входы пользовательского интерфейса представляют значения состояния (рассмотрим, что произойдет, если пользователь закрывает свою вкладку на полпути, и вкладка восстанавливается. Должны ли быть восстановлены все эти значения, которые они заполнили? Если это так, то это состояние). Это может заставить вас чувствовать, что для большой формы нужны десятки или даже сотни форм ввода, но React - это моделирование вашего пользовательского интерфейса в удобной для обслуживания форме: у вас нет 100 независимых полей ввода, у вас есть группы связанных входов, поэтому вы фиксируете каждую из них. сгруппируйте в компонент, а затем создайте свою «основную» форму как набор групп.
MyForm:
render:
<PersonalData/>
<AppPreferences/>
<ThirdParty/>
...
Это также намного легче поддерживать, чем гигантский компонент с одной формой. Разделите группы на Компоненты с поддержкой состояния, где каждый компонент отвечает только за отслеживание нескольких полей ввода одновременно.
Вы также можете почувствовать, что писать весь этот код «хлопотно», но это ложная экономия: разработчики, которые не являются вами, включая вас самих, на самом деле очень выигрывают от того, что все эти входные данные явно подключены, поскольку это значительно облегчает отслеживание путей кода. Тем не менее, вы всегда можете оптимизировать. Например, вы можете написать компоновщик состояния
MyComponent = React.createClass({
getInitialState() {
return {
firstName: this.props.firstName || "",
lastName: this.props.lastName || ""
...: ...
...
}
},
componentWillMount() {
Object.keys(this.state).forEach(n => {
let fn = n + 'Changed';
this[fn] = evt => {
let update = {};
update[n] = evt.target.value;
this.setState(update);
});
});
},
render: function() {
return Object.keys(this.state).map(n => {
<input
key={n}
type="text"
value={this.state[n]}
onChange={this[n + 'Changed']}/>
});
}
});
Конечно, есть улучшенные версии этого, поэтому зайдите на https://npmjs.com и найдите решение для связи с состоянием React, которое вам больше нравится. Open Source - это в основном поиск того, что уже сделали другие, и использование этого вместо того, чтобы писать все с нуля.
Реакция 16 (и 15,5 переходный) и «современный» JS
Начиная с React 16 (и мягкого запуска с 15.5) createClass
вызов больше не поддерживается, и необходимо использовать синтаксис класса. Это меняет две вещи: очевидный синтаксис класса, но также и this
привязку контекста, которая createClass
может делать «бесплатно», поэтому, чтобы убедиться, что все работает, убедитесь, что вы используете нотацию «жирная стрелка» для this
сохранения контекста анонимных функций в onWhatever
обработчиках, таких как onChange
использование мы в коде здесь:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
};
}
render() {
return (
//...
<input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
//...
);
},
updateInputValue(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
Возможно, вы также видели, как люди используют bind
в своем конструкторе все свои функции обработки событий, например:
constructor(props) {
super(props);
this.handler = this.handler.bind(this);
...
}
render() {
return (
...
<element onclick={this.handler}/>
...
);
}
Не делай этого.
Практически каждый раз, когда вы используете bind
, применяется пресловутое «вы делаете это неправильно». Ваш класс уже определяет прототип объекта и поэтому уже определяет контекст экземпляра. Не ставьте bind
верх над этим; используйте обычную пересылку событий вместо дублирования всех ваших вызовов функций в конструкторе, потому что это дублирование увеличивает поверхность вашей ошибки и усложняет отслеживание ошибок, поскольку проблема может быть в вашем конструкторе, а не в том месте, где вы вызываете свой код. А также возлагает бремя обслуживания на других, с которыми вы (имеете или выбираете) работать.
Да, я знаю, что реагирующие доктора говорят, что все в порядке. Это не так, не делай этого.
Реагируйте на 16.8, используя функциональные компоненты с крючками
Начиная с React 16.8, компоненту функции (то есть буквально просто функции, которая принимает некоторые в props
качестве аргумента, можно использовать, как если бы это был экземпляр класса компонента, без написания какого-либо класса), также можно придать состояние посредством использования ловушек .
Если вам не нужен полный код класса, и подойдет одна функция экземпляра, то теперь вы можете использовать useState
ловушку, чтобы получить единственную переменную состояния и ее функцию обновления, которая работает примерно так же, как и в приведенных выше примерах, за исключением setState
вызов функции:
import { useState } from 'react';
function myFunctionalComponentFunction() {
const [input, setInput] = useState(''); // '' is the initial state value
return (
<div>
<label>Please specify:</label>
<input value={input} onInput={e => setInput(e.target.value)}/>
</div>
);
}
Ранее неофициальное различие между классами и компонентами функций заключалось в том, что «функциональные компоненты не имеют состояния», поэтому мы не можем больше скрываться за этим: различие между компонентами функций и компонентами классов можно найти на нескольких страницах очень хорошо. написанная документация о реагировании (нет кратких пояснений, которые могут быть неправильно истолкованы для вас!), которые вы должны прочитать, чтобы знать, что вы делаете, и таким образом знать, выбрали ли вы лучшее (что бы это ни значило для вас) решение для программирования себя из вашей проблемы.
this.onSubmit.bind(this);