Как получить значение поля ввода с помощью ReactJS?


190

У меня есть следующий компонент 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без привязки?
omarjmh

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

Вам нужно привязать onSubmitметод к кнопке отправки (элемент DOM) при нажатии (т.е. onClick={this.onSubmit.bind(this)}). И если вы хотите получить доступ к значению ввода заголовка в форме, которую вы можете использовать onSubmit(event) { const title = event.target.elements.title.value; }.
17

Ответы:


11

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

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

Тогда вы получите результат заголовка


317

Здесь есть три ответа, в зависимости от версии React, с которой вы (вынуждены) работать (ing), и от того, хотите ли вы использовать хуки.

Перво-наперво:

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

Приложения React отображаются на основе двух вещей:

  1. свойства компонента, объявленные любым родительским объектом, создают экземпляр этого компонента, который родитель может изменять на протяжении всего своего жизненного цикла, и
  2. собственное внутреннее состояние компонента, которое он может изменять в течение всего своего жизненного цикла.

То, что вы явно не делаете при использовании React, - это генерирование HTML-элементов, а затем их использование: когда вы говорите React использовать <input>, например, вы не создаете HTML-элемент ввода, вы говорите React создать входной объект React. что происходит с визуализацией в качестве входного элемента HTML, и чье событие обработки выглядит на, но не контролируется , входные событиями HTML элемента.

При использовании React вы создаете элементы пользовательского интерфейса приложения, которые предоставляют пользователю (часто манипулируемые) данные, когда взаимодействие с пользователем изменяет состояние компонента, что может привести к повторному отображению части интерфейса вашего приложения, чтобы отразить новое состояние. В этой модели состояние всегда является окончательным авторитетом, а не «какой бы библиотекой пользовательского интерфейса ни использовался для его визуализации», а в Интернете это DOM браузера. DOM - это почти запоздалая мысль в этой модели программирования: это просто конкретная среда пользовательского интерфейса, которую использует React.

Так что в случае элемента ввода логика:

  1. Вы вводите элемент ввода,
  2. с вашим элементом ввода пока ничего не происходит, событие было перехвачено React и немедленно уничтожено ,
  3. React перенаправляет событие в функцию, которую вы настроили для обработки событий,
  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
    });
  }
});

Таким образом , мы говорим Реагировать использовать 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>
  );
}

Ранее неофициальное различие между классами и компонентами функций заключалось в том, что «функциональные компоненты не имеют состояния», поэтому мы не можем больше скрываться за этим: различие между компонентами функций и компонентами классов можно найти на нескольких страницах очень хорошо. написанная документация о реагировании (нет кратких пояснений, которые могут быть неправильно истолкованы для вас!), которые вы должны прочитать, чтобы знать, что вы делаете, и таким образом знать, выбрали ли вы лучшее (что бы это ни значило для вас) решение для программирования себя из вашей проблемы.


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

5
так что пишите умнее код. входные данные формы наиболее определенно находятся в состоянии (рассмотрим, что происходит, если пользователь закрывает свою вкладку на полпути, и вкладка восстанавливается. Должны ли быть восстановлены все эти заполненные значения? да? это состояние ), поэтому напишите немного кода обслуживания состояния. У Facebook тоже есть сотни форм, и их решением было безумие React. Это работает очень хорошо. Один из способов сделать ваш код немного проще, при этом все еще используя состояние, это использовать двухстороннее связывание состояний , опять же, объясненное на сайте React. Стоит прочтения! =)
Майк «Pomax» Камерманс

2
Также обратите внимание, что «100 полей» в основном не имеет значения: разделите вашу форму, потому что это не 100 элементов, это несколько разделов, каждый из которых содержит несколько входов, поэтому примените хороший дизайн и сделайте каждый раздел отдельным компонентом с группированием компонентов для формы групп. Это обычно делает компонент ответственным за менее чем 10 входных данных, и внезапно ваша информационная архитектура становится намного более понятной. Форма отправки, как действие браузера, конечно, просто видит «вашу форму» и передает все за один раз. Чистый, целевой дизайн пользовательского интерфейса.
Майк 'Pomax' Камерманс

2
Спасибо за комментарии. Однако я заметил, что связывание с состоянием устарело с React v15.
JoeTidee

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

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

Мне удалось это сделать, связав «this» с функцией updateInputValue (evt) с помощью

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

Однако входное значение = {this.state.inputValue} ... оказалось не очень хорошей идеей.

Вот полный код в Babel 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

ваша ошибка из-за того, что вы используете класс, и когда вы используете класс, нам нужно связать функции с помощью This, чтобы работать хорошо. Во всяком случае, есть много учебников, почему мы должны «это» и что такое «это» делать в 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

Было бы хорошо добавить пример правильного добавления ссылок, т.е. используя обратный вызов 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.