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

105

У меня есть следующий компонент 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 - любые идеи, что не так с этим кодом?

  • 5
    this.onSubmit.bind(this);
  • 0
    Хорошо - хочу добавить это как ответ, и я отмечу это галочкой (?)
Показать ещё 7 комментариев
Теги:

6 ответов

154

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

Реагируйте 15 и ниже, с ES5

Делая вещи правильно, согласно документации React и учебникам. Вы пишете пользовательский интерфейс, основанный на двух вещах:

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

То, что вы не делаете - это генерируете DOM-узел элемента ввода и затем вводите его. Вы генерируете пользовательский интерфейс, который должен отображать текстовую строку, которую можно манипулировать, а манипуляции изменяют состояние компонента, что может вызвать повторное отображение. Государство всегда является последней инстанцией, а не DOM. DOM - это запоздалая мысль, это просто конкретная среда пользовательского интерфейса, которую вы используете.

Итак, для правильной работы у вашего компонента есть значение состояния, которое отображается через поле ввода, и мы можем обновить его, заставив этот элемент пользовательского интерфейса отправлять события изменения обратно в компонент:

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
    });
  }
});

Вы вводите элемент input, с вашим элементом input пока ничего не происходит, событие было перехвачено и немедленно updateInputValue, React вместо этого запускает функцию updateInputValue для события. Эта функция запрашивает у React обновить состояние компонента, чтобы оно имело правильное значение, и тогда React может затем повторно представить ваш пользовательский интерфейс с новым обновлением, и только тогда пользовательский интерфейс покажет, что вы ввели букву. И все это происходит за считанные миллисекунды, так что похоже, что вы набрали что-то нормально, но это совсем не то, что произошло.

приложение на основе комментариев

Входные данные пользовательского интерфейса представляют значения состояния (рассмотрим, что происходит, если пользователь закрывает свою вкладку на полпути, и вкладка восстанавливается. Должны ли быть восстановлены все эти значения, которые они заполнили? Если да, то это состояние). Это может заставить вас чувствовать, что для большой формы нужны десятки или даже сотни форм ввода, но 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, применяется пресловутое выражение "вы делаете это неправильно". Ваш класс уже определяет прототип, используйте обычную пересылку событий вместо дублирования всех ваших вызовов функций в конструкторе. Теперь вы увеличили свою поверхность ошибки и усложнили отслеживание ошибок, потому что проблема может быть в вашем конструкторе, а не в том месте, где вы вызываете свой код. В дополнение к бремени обслуживания на других, с которыми вы (имеете или выбираете) работать.

Да, я знаю, что реагирующие документы говорят это хорошо. Это не так, не делай этого.

Реагируйте на 16.8, используя функциональные компоненты с крючками

По состоянию на React 16.8 функцию компоненты (то есть буквально только функция, которая Thats некоторого props в качестве аргумента можно использовать, как будто это экземпляр класса компонента, никогда не писать класс) также может быть предоставлено государством, посредством использования крючков.

Если вам не нужен полный код класса, и подойдет одна функция экземпляра, то теперь вы можете использовать хук useState чтобы получить единственную переменную состояния и ее функцию обновления, которая работает примерно так же, как и в приведенных выше примерах, за исключением без setState функции 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>
  );
}

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

  • 3
    Я прочитал несколько статей в Интернете, в которых говорится, что использование слишком большого количества состояний - плохая идея. В одной конкретной форме моего приложения у меня есть около 100 полей формы. Определение функции для сохранения состояния ощущается как излишне трудный способ ведения дел. Если я могу использовать onClick = {this.onSubmit.bind (this)}, это похоже на хороший способ получить значение (тогда, если я хочу, установите состояние компонентов) - я был бы признателен за некоторые комментарии по этому поводу.
  • 5
    так что пишите умнее код. входные данные формы наиболее определенно находятся в состоянии (рассмотрим, что происходит, если пользователь закрывает свою вкладку на полпути, и вкладка восстанавливается. Должны ли быть восстановлены все эти заполненные значения? да? это состояние ), поэтому напишите немного кода обслуживания состояния. У Facebook тоже есть сотни форм, и их решением для безумия было React. Это работает очень хорошо. Один из способов сделать ваш код немного проще, при этом все еще используя состояние, это использовать двухстороннее связывание состояний , опять же, объясненное на сайте React. Стоит прочтения! знак равно
Показать ещё 14 комментариев
6

Удалось получить значение поля ввода, выполнив что-то вроде этого:

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
6

В реакции 16 я использую

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />
  • 0
    не работает, если поле было заполнено автоматически при возрастной нагрузке
3

Мне удалось это сделать, привязав "this" к функции updateInputValue (evt) с

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

Однако входное value = {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" и что "this" делать в javascript.

если вы исправите кнопку отправки, это должно быть:

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

а также если вы хотите показать значение этого ввода в консоли, вы должны использовать var title= this.title.value;

  • 1
    эта ссылка может быть полезна, если вы хотите узнать больше об этом
  • 0
    medium.com/@housecor/...
0

Вы можете получить входное значение без добавления функции onChange.

Просто добавьте элемент ввода a 'ref attr:

И затем используйте this.refs, чтобы получить входное значение, когда вам это нужно.

  • 2
    Это больше не рекомендуется.
  • 0
    @JoeTidee почему?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню