Jak uzyskać wartość pola wejściowego za pomocą ReactJS?

188

Mam następujący składnik 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>
            ...
        );
    }

};

Konsola daje mi undefined- jakieś pomysły, co jest nie tak z tym kodem?

JoeTidee
źródło
7
this.onSubmit.bind(this);
zerkms
Fajnie - chcę dodać to jako odpowiedź, a ja
zaznaczę
2
a co e.target.valuebez wiązania?
omarjmh 18.04.16
1
czy wartość e.target.value nie byłaby kierowana na przycisk, a nie na pole wprowadzania?
JoeTidee 18.04.16
Musisz powiązać onSubmitmetodę z przyciskiem wysyłania (elementem DOM) po kliknięciu (tj onClick={this.onSubmit.bind(this)}.). A jeśli chcesz uzyskać dostęp do wartości tytułu tytułu w formularzu, którego możesz użyć onSubmit(event) { const title = event.target.elements.title.value; }.
tfmontague

Odpowiedzi:

10

Należy użyć konstruktora w klasie MyComponent, która rozszerza React.Component

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

Otrzymasz wynik tytułu

Md. Maidul Islam
źródło
314

Istnieją tutaj trzy odpowiedzi, w zależności od wersji React, z którą jesteś (zmuszony) pracować (i) i od tego, czy chcesz użyć haków.

Po pierwsze:

Ważne jest, aby zrozumieć, w jaki sposób reagować prace, dzięki czemu można zrobić rzeczy właściwie (protip: to jest bardzo warto przebiegającej przez React samouczka ćwiczenia na React internetową Jest dobrze napisana i obejmuje wszystkie podstawy w taki sposób, że faktycznie wyjaśnia, jak to zrobić. rzeczy). „Prawidłowo” oznacza tutaj, że piszesz interfejs aplikacji, który jest renderowany w przeglądarce; cała praca interfejsu odbywa się w React, a nie w „tym, do czego jesteś przyzwyczajony, gdy piszesz stronę internetową” (dlatego aplikacje React to „aplikacje”, a nie „strony internetowe”).

Aplikacje React są renderowane na podstawie dwóch rzeczy:

  1. właściwości komponentu zadeklarowane przez którykolwiek z elementów nadrzędnych tworzy instancję tego składnika, którą element nadrzędny może modyfikować przez cały cykl życia, oraz
  2. własny stan wewnętrzny komponentu, który może modyfikować sam w całym cyklu życia.

To, czego wyraźnie nie robisz, gdy używasz React, to generowanie elementów HTML, a następnie ich używanie: kiedy mówisz Reactowi, aby <input>na przykład używał , np. Nie tworzysz elementu wejściowego HTML, mówisz Reactowi, aby utworzył obiekt wejściowy React które zdarza się renderować jako element wejściowy HTML, a obsługa zdarzeń patrzy na zdarzenia wejściowe elementu HTML, ale nie jest przez nie kontrolowana .

Korzystając z React, generujesz elementy interfejsu aplikacji, które prezentują użytkownikowi (często manipulowane) dane, a interakcja użytkownika zmienia stan składnika, co może spowodować ponowne przesłanie części interfejsu aplikacji w celu odzwierciedlenia nowego stanu. W tym modelu stan jest zawsze ostatecznym organem, a nie „dowolną biblioteką interfejsu użytkownika używaną do jego renderowania”, która w sieci WWW jest DOM przeglądarki. W tym modelu programowania DOM jest niemal ponownym przemyśleniem: jest to konkretna struktura interfejsu użytkownika, z której korzysta React.

W przypadku elementu wejściowego logika jest następująca:

  1. Wpisujesz element wejściowy,
  2. nic się nie dzieje z twoim elementem wejściowym, zdarzenie zostało przechwycone przez React i natychmiast zabite ,
  3. React przekazuje zdarzenie do funkcji skonfigurowanej do obsługi zdarzeń,
  4. ta funkcja może zaplanować aktualizację stanu,
  5. jeśli tak się stanie, React uruchomi tę aktualizację stanu (asynchronicznie!) i wyzwoli renderpołączenie po aktualizacji, ale tylko jeśli aktualizacja stanu zmieni stan.
  6. dopiero po tym renderowaniu interfejs użytkownika pokaże, że „wpisałeś literę”.

Wszystko to dzieje się w ciągu kilku milisekund, jeśli nie mniej, więc wygląda na to, że wpisałeś się do elementu wejściowego w taki sam sposób, w jaki zwykłeś „po prostu używać elementu wejściowego na stronie”, ale to absolutnie nie to stało się.

Powiedziawszy to, jak uzyskać wartości z elementów w React:

Reaguj 15 i poniżej za pomocą ES5

Aby zrobić to poprawnie, twój komponent ma wartość stanu, która jest wyświetlana przez pole wejściowe, i możemy go zaktualizować, sprawiając, że element interfejsu użytkownika wysyła zdarzenia zmiany z powrotem do komponentu:

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

Tak powiemy React korzystać z updateInputValuefunkcji do obsługi interakcji użytkownika, użycie setStatezaplanować aktualizację stanu, oraz fakt, że rendersięga do this.state.inputValueśrodków, które gdy rerenders po aktualizacji stanu, użytkownik zobaczy tekst aktualizacji w oparciu o to, co wpisane.

uzupełnienie na podstawie komentarzy

Biorąc pod uwagę, że dane wejściowe interfejsu użytkownika reprezentują wartości stanu (zastanów się, co się stanie, jeśli użytkownik zamknie kartę w połowie, a karta zostanie przywrócona. Czy wszystkie te wartości, które wprowadzili, powinny zostać przywrócone? Jeśli tak, to stan). To może sprawić, że poczujesz, że duża forma potrzebuje dziesiątek, a nawet stu formularzy wejściowych, ale React polega na modelowaniu interfejsu użytkownika w sposób możliwy do utrzymania: nie masz 100 niezależnych pól wejściowych, masz grupy powiązanych danych wejściowych, więc przechwytujesz każdy zgrupuj w komponencie, a następnie utwórz formularz „master” jako zbiór grup.

MyForm:
  render:
    <PersonalData/>
    <AppPreferences/>
    <ThirdParty/>
     ...

Jest to również o wiele łatwiejsze w utrzymaniu niż gigantyczny pojedynczy komponent. Podziel grupy na komponenty z zachowaniem stanu, przy czym każdy komponent odpowiada tylko za śledzenie kilku pól wejściowych na raz.

Może się również wydawać, że napisanie całego kodu jest „kłopotliwe”, ale to fałszywa oszczędność: programiści, którzy nie są Tobą, w tym Ty, w rzeczywistości, czerpią ogromne korzyści z tego, że wszystkie te dane wejściowe są wyraźnie połączone, ponieważ znacznie ułatwia śledzenie ścieżek kodu. Zawsze możesz jednak zoptymalizować. Na przykład możesz napisać linker stanu

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']}/>
    });
  }
});

Oczywiście istnieją ulepszone wersje tego, więc wejdź na https://npmjs.com i poszukaj rozwiązania łączenia stanu React, które najbardziej Ci się podoba. Open Source polega głównie na znalezieniu tego, co inni już zrobili, i wykorzystaniu tego zamiast pisania wszystkiego od zera.

React 16 (i 15.5 przejściowy) i „nowoczesny” JS

Począwszy od React 16 (i miękkiego startu z 15.5), createClasswywołanie nie jest już obsługiwane i należy użyć składni klas. Zmienia to dwie rzeczy: oczywistą składnię klas, ale także thispowiązanie kontekstu, które createClassmożna wykonać „za darmo”, więc aby upewnić się, że wszystko nadal działa, upewnij się, że używasz notacji „gruba strzałka” dla thiszachowania kontekstu w funkcjach onWhateverobsługi, takich jak onChangeużycie my w kod tutaj:

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

Możliwe, że widziałeś, jak ludzie używają bindkonstruktora do wszystkich funkcji obsługi zdarzeń, takich jak:

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

render() {
  return (
    ...
    <element onclick={this.handler}/>
    ...
  );
}

Nie rób tego

Prawie za każdym razem, gdy używasz bind, obowiązuje przysłowiowe „robisz to źle”. Twoja klasa już definiuje prototyp obiektu, a więc już definiuje kontekst instancji. Nie kończ bindtego; używaj normalnego przekazywania zdarzeń zamiast duplikowania wszystkich wywołań funkcji w konstruktorze, ponieważ to powielanie zwiększa powierzchnię błędu i znacznie utrudnia śledzenie błędów, ponieważ problem może znajdować się w konstruktorze zamiast w miejscu, w którym wywołujesz kod. Oprócz nakładania ciężarów związanych z utrzymaniem na inne osoby, z którymi (z wyboru lub z wyboru) współpracujesz.

Tak, wiem, że doktorzy z reakcji mówią, że jest w porządku. Nie, nie rób tego.

Reaguj 16.8, używając komponentów funkcji z zaczepami

Od React 16.8 komponent funkcji (tj. Dosłownie tylko funkcja, która przyjmuje propsargument jako argument, może być używany tak, jakby był instancją klasy komponentu, bez pisania klasy), może również zostać podany stan, poprzez użycie hooków .

Jeśli nie potrzebujesz pełnego kodu klasy, a zadziała funkcja pojedynczej instancji, możesz teraz użyć useStatehaka, aby uzyskać sobie pojedynczą zmienną stanu, i jej funkcję aktualizacji, która działa mniej więcej tak samo jak powyższe przykłady, z wyjątkiem braku setStatewywołanie funkcji:

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

Wcześniej nieoficjalnym rozróżnieniem między klasami i komponentami funkcji było „komponenty funkcji nie mają stanu”, więc nie możemy się już dłużej za tym kryć: różnica między komponentami funkcji i komponentami klas można znaleźć na kilku stronach bardzo dobrze - pisemna reakcja na dokumentację (bez skrótu wyjaśnienia jednej linijki, aby wygodnie dla ciebie źle zinterpretować!), którą powinieneś przeczytać, abyś wiedział, co robisz, a tym samym wiedzieć, czy wybrałeś najlepsze (cokolwiek to dla ciebie znaczy) rozwiązanie do samodzielnego zaprogramowania z powodu twojego problemu.

Mike „Pomax” Kamermans
źródło
4
Przeczytałem kilka artykułów online, które mówią, że użycie zbyt dużej ilości stanu to zły pomysł. W jednej konkretnej formie mojego wniosku mam około 100 pól formularza. Zdefiniowanie funkcji ratowania stanu wydaje się niepotrzebnie uciążliwym sposobem robienia rzeczy. Jeśli mogę użyć onClick = {this.onSubmit.bind (this)}, wydaje się to dobrym sposobem na uzyskanie wartości (wtedy, jeśli chcę, ustaw stan składników) - byłbym wdzięczny za kilka komentarzy na ten temat.
JoeTidee 18.04.16
5
więc napisz mądrzejszy kod. dane wejściowe formularza są zdecydowanie stanowe (zastanów się, co się stanie, jeśli użytkownik zamknie kartę w połowie, a karta zostanie przywrócona. Czy wszystkie te wartości, które wprowadzili, powinny zostać przywrócone? tak? to jest stan ), więc napisz trochę kodu obsługi stanu. Facebook ma również setki wartości formy, a ich rozwiązaniem szaleństwa było React. Działa naprawdę dobrze. Jednym ze sposobów, aby twój kod był trochę łatwiejszy, podczas gdy nadal używasz stanu, jest użycie dwukierunkowego połączenia stanu , znowu wyjaśnione na stronie React. Warte przeczytania! =)
Mike 'Pomax' Kamermans
2
Zauważ też, że „100 pól” jest w większości nieistotne: podziel formularz, ponieważ nie jest to 100 elementów, to kilka sekcji, każda z wieloma danymi wejściowymi, więc zastosuj dobry projekt i ustaw każdą sekcję jako własny komponent, z grupowaniem komponentów dla formularza grupy. Zwykle powoduje to, że komponent odpowiada za mniej niż 10 danych wejściowych, i nagle architektura informacji staje się znacznie bardziej sensowna. Formularz przesłania, jako działanie przeglądarki, oczywiście widzi „twój formularz” i przesyła wszystko za jednym razem. Czysty, ukierunkowany projekt interfejsu użytkownika.
Mike 'Pomax' Kamermans
2
Dziękuję za komentarze. Zauważyłem jednak, że łączenie stanu jest przestarzałe od wersji 15 programu React.
JoeTidee 18.04.16
3
@JasonChing, po prostu wbudowałeś potencjalne błędy w swoim kodzie. React nie jest „być wszystkim skończyć wszystkie” rozwiązanie dla stron internetowych, to framework do budowania interfejsów, a ona jest odpowiedzialna za zarządzanie państwową i rzeczywistego renderowania UI jako refleksja (użytkownicy nie współpracują z DOM, ich interakcji z Reakcja. Aktualizacje DOM są po prostu asynchronicznym (ale niezwykle szybkim) ostatnim krokiem, aby interfejs użytkownika wizualnie odzwierciedlał stan). Jeśli chcesz to obejść, ważniejsze pytanie brzmi: dlaczego używasz React? Ponieważ najlepszym znakiem, że używasz go źle, jest połączenie React i jQuery.
Mike „Pomax” Kamermans
17

Udało się uzyskać wartość pola wejściowego, wykonując coś takiego:

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
Hugo Wesley
źródło
1
Dlaczego warto korzystać z „setState”? Wymaga to ponownego renderowania ... prawda?
Luca Davanzo
15

W reakcji 16 używam

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />
Pyae Sone
źródło
nie działa, jeśli pole zostało wypełnione automatycznie po obciążeniu wiekowym
SeanMC
4

Udało mi się to zrobić, wiążąc „to” z funkcją updateInputValue (evt) za pomocą

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

Jednak wartość wejściowa = {this.state.inputValue} ... nie była dobrym pomysłem.

Oto pełny kod w 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;
   }
}
Matthias Liszt
źródło
2

twój błąd jest spowodowany tym, że używasz klasy, a kiedy używasz klasy, musimy połączyć funkcje z This, aby dobrze działać. w każdym razie istnieje wiele samouczków, dlaczego powinniśmy „to” i co to jest „robić” w javascript.

jeśli poprawisz przycisk wysyłania, powinno to działać:

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

a także jeśli chcesz pokazać wartość tego wejścia w konsoli, powinieneś użyć var ​​title = this.title.value;

Soroush Bk
źródło
2
ten link może być pomocny, jeśli chcesz dowiedzieć się więcej o „tym”
Soroush Bk
2

Podaj <input>unikalny identyfikator

<input id='title' ...>

a następnie użyj standardowego interfejsu API sieci Web, aby odwołać się do niego w DOM

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

Nie ma potrzeby ciągłego aktualizowania stanu React przy każdym naciśnięciu klawisza. Po prostu uzyskaj wartość, gdy jest wymagana.

Brent Washburne
źródło
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="[email protected]" />
Kidali Kevin
źródło
choć Twoja odpowiedź może być dobra na pytanie, zawsze lepiej jest dodać wyjaśnienie. Poświęć 2 minuty, aby go dodać. Poprawi to twoją odpowiedź również dla przyszłych użytkowników.
DaFois,
jasne, zrobię to.
Kidali Kevin
0

Można uzyskać wartość wejściową bez dodawania funkcji „onChange”.

Wystarczy dodać do elementu wejściowego „ref attr:

A następnie użyj this.refs, aby uzyskać wartość wejściową, gdy jej potrzebujesz.

E1ad
źródło
3
Nie jest to już zalecane.
JoeTidee
1
Możesz z nich korzystać, ale zaleca się utrzymywanie przepływu danych w jednym kierunku za pomocą rekwizytów i wywołań zwrotnych.
JoeTidee
Dobrze byłoby dodać przykład poprawnego dodawania referencji, tj. Korzystanie z wywołania zwrotnego ref zamiast starszego ciągu.
JoeTidee
0

Zmień swoje oznaczenie na: ref='title'i usuń name='title' Następnie usuń var title = this.titlei napisz:

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

Powinieneś także dodać .bind(this)dothis.onSubmit

(Działało w moim przypadku, które było dość podobne, ale zamiast tego onClickmiałem onSubmit={...}i zostało zapisane w formie ( <form onSubmit={...} ></form>))

Katarzyna Wrońska
źródło
0

jeśli używasz komponentu klasy, to tylko 3 kroki - najpierw musisz zadeklarować stan dla swoich danych wejściowych, na przykład this.state = {name: ''} . Po drugie, musisz napisać funkcję do ustawiania stanu, gdy zmienia się ona w poniższym przykładzie, to setName () i na koniec musisz napisać wejściowy jsx, na przykład <wartość wejściowa = {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
Lord
źródło
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>
        ...
    );
}

};
Pranav Agarwal
źródło
0

za pomocą niekontrolowanych pól:

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

};
Georg
źródło