Як отримати значення поля введення за допомогою ReactJS?


188

У мене є такий компонент React:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        var title = this.title;
        console.log(title);
    }

    render(){
        return (
            ...
            <form className="form-horizontal">
                ...
                <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" onClick={this.onSubmit} className="btn">Save</button>
            ...
        );
    }

};

Консоль дає мені undefined- будь-які ідеї, що з цим кодом не так?


7
this.onSubmit.bind(this);
zerkms

Приємно - хочу додати його як відповідь, і я
позначу

2
а як e.target.valueбез прив’язки?
омарім

1
не буде e.target.value орієнтуватися на кнопку, а не на поле введення?
JoeTidee

Вам потрібно прив’язати onSubmitметод до кнопки подання (елемент DOM) при натисканні (тобто onClick={this.onSubmit.bind(this)}). І якщо ви хочете отримати доступ до значення вводу заголовка у формі, яку ви можете використовувати onSubmit(event) { const title = event.target.elements.title.value; }.
tfmontague

Відповіді:


10

Ви повинні використовувати конструктор під класом MyComponent extends React.Component

constructor(props){
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
  }

Тоді ви отримаєте результат титулу


315

Тут є три відповіді, залежно від версії React, з якою ви (змушені) працювати, і від того, чи хочете ви використовувати гачки.

Насамперед:

Важливо зрозуміти, як працює React, щоб ви могли робити все належним чином (protip: надзвичайно варто запустити вправу React на веб-сайті React. Це добре написано та охоплює всі основи так, що насправді пояснює, як робити речі). "Правильно" тут означає, що ви пишете інтерфейс програми, який, мабуть, відображається в браузері; вся робота інтерфейсу відбувається в React, а не в тому, "до чого ти звик, якщо пишеш веб-сторінку" (саме тому програми React - це "програми", а не "веб-сторінки").

Програми реагування відображаються на основі двох речей:

  1. властивості компонента, задекларовані будь-яким з батьків, створює екземпляр цього компонента, який батько може змінювати протягом свого життєвого циклу, і
  2. власний внутрішній стан компонента, який він може змінювати протягом свого власного життєвого циклу.

Те, що ви явно не робите при використанні React, - це генерування HTML-елементів, а потім їх використання: коли ви скажете React використовувати <input>, наприклад, ви не створюєте елемент введення HTML, ви говорите React створити об'єкт введення React. це трапляється, що він відображається як елемент введення HTML, а обробка подій розглядається, але не контролюється подіями введення HTML-елемента.

Використовуючи React, ви створюєте елементи інтерфейсу програми, які представляють користувачеві (часто маніпулювані) дані, при цьому взаємодія з користувачем змінює стан компонента, що може спричинити повторне відображення частини інтерфейсу вашої програми для відображення нового стану. У цій моделі стан завжди є остаточним повноваженням, а не "якоюсь бібліотекою користувальницького інтерфейсу використовується для його надання", що в Інтернеті є ДОМ браузера. DOM майже не замислюється в цій моделі програмування: React використовує саме ту конкретну структуру інтерфейсу.

Отже, у випадку вхідного елемента логіка полягає в наступному:

  1. Ви вводите елемент введення,
  2. з вашим вхідним елементом ще нічого не відбувається, подія React перехопила та негайно вбила ,
  3. Реагуйте, пересилає подію на функцію, яку ви встановили для обробки подій,
  4. ця функція може запланувати оновлення стану,
  5. якщо це так, React запускає це оновлення стану (асинхронно!) і викликає renderвиклик після оновлення, але тільки якщо оновлення стану змінило стан.
  6. лише після цього візуалізації інтерфейс покаже, що ви "набрали лист".

Все це відбувається за лічені мілісекунди, якщо не менше, тож, схоже, ви ввели вхідний елемент тим же способом, до якого ви звикли, "просто використовуючи елемент введення на сторінці", але це абсолютно не те, що сталося.

Отже, з урахуванням сказаного, про те, як отримати значення з елементів в 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>
  );
}

Раніше неофіційне розмежування класів та функціональних компонентів було "функціональні компоненти не мають стану", тому ми вже не можемо ховатися за цим: різницю між функціональними компонентами та компонентами класів можна знайти дуже поширеною на декілька сторінок. - написана документація про реакцію (жодне ярликове пояснення одного вкладиша для зручного неправильного тлумачення для вас!), яке ви повинні прочитати, щоб ви знали, що робите, і таким чином могли знати, чи вибрали ви найкраще (все, що для вас означає) рішення програмувати самостійно з проблеми, у вас є.


4
Я прочитав кілька статей в Інтернеті, в яких говориться, що використання занадто великої кількості стану - це погана ідея. В одній конкретній формі моєї заявки я маю близько 100 форм форм. Визначення функції для збереження держави відчуває себе як надмірно важкий спосіб робити справи. Якщо я можу використовувати onClick = {this.onSubmit.bind (this)}, це здається хорошим способом отримати значення (тоді, якщо я хочу, встановіть стан компонентів) - я вдячний за деякі коментарі з цього приводу.
JoeTidee

5
тому пишіть розумніший код. вхідні дані форми - це напевно стан (врахуйте, що станеться, якщо користувач закриє вкладку посередині, а вкладку відновлено. Чи повинні бути відновлені всі ці значення, які він заповнив? так? це стан ), тому напишіть трохи коду технічного обслуговування штату. У Facebook теж є сотні значень форми, і їх рішенням для божевілля стало Реагувати. Це працює дуже добре. Один із способів зробити свій код трохи простішим, використовуючи стан, - це знову використовувати двостороннє посилання , пояснене на сайті React. Варто прочитати! =)
Майк 'Pomax' Камерманс

2
Також зауважте, що "100 полів" здебільшого не має значення: розділіть свою форму, оскільки це не 100 елементів, це кілька розділів, кожен з декількома входами, тому застосуйте гарний дизайн і зробіть кожен розділ власним компонентом, згрупуючи компоненти за формою групи. Зазвичай цей компонент відповідає за менше 10 входів, і раптом ваша інформаційна архітектура має набагато більше сенсу. Форма подання, як дія браузера, звичайно просто бачить "вашу форму" і подає все за один раз. Чистий, націлений дизайн інтерфейсу користувача.
Майк 'Помакс' Камерманс

2
Дякуємо за коментарі. Однак я помітив, що стані зв’язків старій давності були припинені станом на React v15.
JoeTidee

3
@JasonChing тоді ви просто вбудували потенційні помилки у свій код. React не є рішенням "бути всім, кінцем усіх" для веб-сторінок, це рамка для створення інтерфейсів, і вона відповідає за управління державою та фактичне надання інтерфейсу користувача як заздалегідь (ваші користувачі не взаємодіють з DOM, вони взаємодіють з Реагуйте: оновлення DOM - це просто асинхронний (але неймовірно швидкий) останній крок, щоб інтерфейс користувача візуально відображав стан). Якщо ви хочете обійти це, важливішим питанням є: чому ви використовуєте React? Оскільки найкращий знак, який ви неправильно використовуєте, - це поєднання React та jQuery.
Майк 'Помакс' Камерманс

17

Вдалося отримати значення поля введення, зробивши щось подібне:

import React, { Component } from 'react';

class App extends Component {

constructor(props){
super(props);

this.state = {
  username : ''
}

this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}


updateInput(event){
this.setState({username : event.target.value})
}


handleSubmit(){
console.log('Your input value is: ' + this.state.username)
//Send state to the server code
}



render(){
return (
    <div>
    <input type="text" onChange={this.updateInput}></input>
    <input type="submit" onClick={this.handleSubmit} ></input>
    </div>
  );
}
} 

//output
//Your input value is: x

1
Навіщо використовувати "setState"? Це передбачає повторну візуалізацію ... чи не так?
Лука Даванцо

15

У реакції 16 я використовую

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />

не працює, якщо поле автоматично заповнюється у віковому навантаженні
SeanMC

4

Мені вдалося це зробити, прив’язавши "це" до функції updateInputValue (evt) за допомогою

this.updateInputValue = this.updateInputValue.bind (це);

Однак вхідне значення = {this.state.inputValue} ... виявилося непоганою ідеєю.

Ось повний код у вабелі ES6:

class InputField extends React.Component{


  constructor(props){
   super(props);
   //this.state={inputfield: "no value"};   
   this.handleClick = this.handleClick.bind(this);
   this.updateInputValue = this.updateInputValue.bind(this);
  }

  handleClick(){
   console.log("trying to add picture url");
   console.log("value of input field : "+this.state.inputfield);

  }

  updateInputValue(evt){
    //console.log("input field updated with "+evt.target.value);
    this.state={inputfield: evt.target.value};   

  }

  render(){
    var r; 
    r=<div><input type="text" id="addpixinputfield" 
            onChange={this.updateInputValue} />
      <input type="button" value="add" id="addpix" onClick={this.handleClick}/>
      </div>;    
    return r;
   }
}

2

Ваша помилка полягає в тому, що ви використовуєте клас, а при використанні класу нам потрібно зв’язати функції з цим, щоб добре працювати. у будь-якому випадку є дуже багато підручників, чому ми повинні "це" і що "це" робити в JavaScript.

якщо ви виправите кнопку подання, це має бути спрацьовувати:

<button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>

а також якщо ви хочете показати значення цього вводу в консолі, ви повинні використовувати var title = this.title.value;


2
це посилання може бути корисним, якщо ви хочете дізнатися більше про "це"
Soroush Bk


2

Надайте <input>унікальний ідентифікатор

<input id='title' ...>

а потім використовуйте стандартний веб-API для посилання на нього в DOM

const title = document.getElementById('title').value

Немає необхідності постійно оновлювати стан React кожним натисканням клавіші. Просто отримайте значення, коли це потрібно.


1
// On the state
constructor() {
  this.state = {
   email: ''
 }
}

// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}

<Input 
  value={this.state.email ? this.state.email : ''} 
  onChange={event => this.setState({ email: event.target.value)}
  type="text" 
  name="emailAddress" 
  placeholder="johdoe@somewhere.com" />

хоча ваша відповідь може бути хорошою для питання, завжди краще додати пояснення. Будь ласка, знайдіть 2 хвилини, щоб додати його. Це покращить вашу відповідь і для майбутніх користувачів.
DaFois

звичайно, я це зроблю.
Кідалі Кевін

0

Ви можете отримати вхідне значення без додавання функції "onChange".

Просто додайте до вхідного елемента 'ref attr:

А потім скористайтеся this.refs, щоб отримати вхідне значення, коли воно вам потрібно.


3
Це більше не рекомендується.
JoeTidee

1
Ви можете використовувати їх, але рекомендується тримати потік даних в одному напрямку, використовуючи реквізити та зворотні дзвінки.
JoeTidee

Було б добре додати приклад правильного додавання refs, тобто використання зворотного виклику ref замість застарілого рядка.
JoeTidee

0

Змініть свою посилання на: ref='title'і видаліть name='title' Потім видаліть var title = this.titleі напишіть:

console.log(this.refs.title.value)

Також слід додати .bind(this)доthis.onSubmit

(Він працював у моєму випадку, який був досить схожим, але замість цього onClickя мав onSubmit={...}і був викладений у форму ( <form onSubmit={...} ></form>))


0

якщо ви використовуєте компонент класу, то лише 3 кроки - спочатку вам потрібно оголосити стан для вашого вводу, наприклад, this.state = {name: ''} . По-друге, вам потрібно написати функцію для встановлення стану, коли вона змінюється в нижченаведеному прикладі, це setName (), і, нарешті, ви повинні написати вхідний jsx, наприклад <input value = {this.name} onChange = {this.setName} />

import React, { Component } from 'react'

export class InputComponents extends Component {
    constructor(props) {
        super(props)

        this.state = {
             name:'',
             agree:false
        }
        this.setName = this.setName.bind(this);
        this.setAgree=this.setAgree.bind(this);
    }

    setName(e){
        e.preventDefault();
        console.log(e.target.value);
        this.setState({
            name:e.target.value
        })
    }
    setAgree(){
        this.setState({
            agree: !this.state.agree
        }, function (){
            console.log(this.state.agree);
        })
    }
    render() {
        return (
            <div>
                <input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
                < input value={this.state.name} onChange = {this.setName}/>
            </div>
        )
    }
}

export default InputComponents

0
export default class MyComponent extends React.Component {

onSubmit(e) {
    e.preventDefault();
    var title = this.title.value; //added .value
    console.log(title);
}

render(){
    return (
        ...
        <form className="form-horizontal">
            ...
            <input type="text" className="form-control" ref={input => this.title = input} name="title" />
            ...
        </form>
        ...
        <button type="button" onClick={this.onSubmit} className="btn">Save</button>
        ...
    );
}

};

0

використання неконтрольованих полів:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        console.log(e.target.neededField.value);
    }

    render(){
        return (
            ...
            <form onSubmit={this.onSubmit} className="form-horizontal">
                ...
                <input type="text" name="neededField" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" className="btn">Save</button>
            ...
        );
    }

};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.