Тут є три відповіді, залежно від версії React, з якою ви (змушені) працювати, і від того, чи хочете ви використовувати гачки.
Насамперед:
Важливо зрозуміти, як працює React, щоб ви могли робити все належним чином (protip: надзвичайно варто запустити вправу React на веб-сайті React. Це добре написано та охоплює всі основи так, що насправді пояснює, як робити речі). "Правильно" тут означає, що ви пишете інтерфейс програми, який, мабуть, відображається в браузері; вся робота інтерфейсу відбувається в React, а не в тому, "до чого ти звик, якщо пишеш веб-сторінку" (саме тому програми React - це "програми", а не "веб-сторінки").
Програми реагування відображаються на основі двох речей:
- властивості компонента, задекларовані будь-яким з батьків, створює екземпляр цього компонента, який батько може змінювати протягом свого життєвого циклу, і
- власний внутрішній стан компонента, який він може змінювати протягом свого власного життєвого циклу.
Те, що ви явно не робите при використанні React, - це генерування HTML-елементів, а потім їх використання: коли ви скажете React використовувати <input>
, наприклад, ви не створюєте елемент введення HTML, ви говорите React створити об'єкт введення React. це трапляється, що він відображається як елемент введення HTML, а обробка подій розглядається, але не контролюється подіями введення HTML-елемента.
Використовуючи React, ви створюєте елементи інтерфейсу програми, які представляють користувачеві (часто маніпулювані) дані, при цьому взаємодія з користувачем змінює стан компонента, що може спричинити повторне відображення частини інтерфейсу вашої програми для відображення нового стану. У цій моделі стан завжди є остаточним повноваженням, а не "якоюсь бібліотекою користувальницького інтерфейсу використовується для його надання", що в Інтернеті є ДОМ браузера. DOM майже не замислюється в цій моделі програмування: 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
});
}
});
Таким чином, ми кажемо React використовувати updateInputValue
функцію для обробки взаємодії з користувачем, використовувати setState
для планування оновлення стану, а також те, що render
натискає на нього, this.state.inputValue
означає, що після повторного оновлення після оновлення стану користувач побачить текст оновлення на основі того, що він ввів.
додаток на основі коментарів
Зважаючи на те, що входи UI представляють значення стану (врахуйте, що станеться, якщо користувач закриє вкладку посередині, а вкладку відновлено. Чи повинні бути відновлені всі ці заповнені значення? Якщо так, то це стан). Це може змусити вас відчувати, що для великої форми потрібні десятки чи навіть сотня форм введення, але 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 перехідних) та "сучасний" СВ
Станом на 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);