Ci sono tre risposte qui, a seconda della versione di React con cui sei (costretto a) lavorare (ing) e se vuoi usare gli hook.
Cominciando dall'inizio:
E 'importante capire come React lavori, in modo da poter fare le cose per bene (PROTIP: si tratta di è eccellente pena in esecuzione attraverso la Reagire esercizio tutorial sul sito Reagire E' ben scritto, e copre tutte le basi in modo che in realtà spiega come fare. cose). "Correttamente" qui significa che stai scrivendo un'interfaccia dell'applicazione che sembra essere visualizzata in un browser; tutto il lavoro dell'interfaccia avviene in React, non in "quello a cui sei abituato se stai scrivendo una pagina web" (ecco perché le app React sono "app", non "pagine web").
Le applicazioni React sono rese in base a due cose:
- le proprietà del componente dichiarate dal genitore crea un'istanza di quel componente, che il genitore può modificare durante il suo ciclo di vita, e
- lo stato interno del componente, che può modificarsi durante il suo intero ciclo di vita.
Quello che stai esplicitamente non fare quando si utilizza reagire sta generando elementi HTML e quindi utilizzando quelli: quando dite Reagire ad utilizzare un <input>
, per esempio, si sta non crea un elemento di input HTML, si indica reagire a creare un oggetto di input Reagire che viene visualizzato come elemento di input HTML e la cui gestione degli eventi guarda, ma non è controllato da , gli eventi di input dell'elemento HTML.
Quando si utilizza React, ciò che si sta facendo è generare elementi dell'interfaccia utente dell'applicazione che presentano all'utente dati (spesso manipolabili), con l'interazione dell'utente che modifica lo stato del componente, il che può causare un rendering di una parte dell'interfaccia dell'applicazione in modo da riflettere il nuovo stato. In questo modello, lo stato è sempre l'autorità finale, non "qualunque sia la libreria dell'interfaccia utente utilizzata per renderlo", che sul Web è il DOM del browser. Il DOM è quasi un ripensamento in questo modello di programmazione: è solo il particolare framework dell'interfaccia utente che React utilizza.
Quindi, nel caso di un elemento di input, la logica è:
- Si digita l'elemento di input,
- non succede ancora nulla al tuo elemento di input, l'evento è stato intercettato da React e ucciso immediatamente ,
- React inoltra l'evento alla funzione che hai impostato per la gestione degli eventi,
- tale funzione può programmare un aggiornamento dello stato,
- in tal caso, React esegue tale aggiornamento di stato (in modo asincrono!) e attiverà una
render
chiamata dopo l'aggiornamento, ma solo se l'aggiornamento di stato ha cambiato lo stato.
- solo dopo aver eseguito questo rendering l'interfaccia utente mostrerà che "hai digitato una lettera".
Tutto ciò accade in pochi millisecondi, se non di meno, quindi sembra che tu abbia digitato l'elemento di input nello stesso modo in cui sei abituato a "semplicemente usare un elemento di input in una pagina", ma non è assolutamente quello è accaduto.
Quindi, detto questo, su come ottenere valori dagli elementi in React:
Reagire 15 e sotto, con ES5
Per fare le cose correttamente, il tuo componente ha un valore di stato, che viene mostrato tramite un campo di input, e possiamo aggiornarlo facendo in modo che l'elemento UI rispedisca gli eventi di modifica nel componente:
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
});
}
});
Quindi diciamo a reagire a utilizzare la updateInputValue
funzione per gestire l'interazione con l'utente, l'uso setState
di programmare l'aggiornamento di stato, e il fatto che render
attinge this.state.inputValue
significa che quando si rigenera dopo l'aggiornamento dello stato, l'utente vedrà il testo di aggiornamento in base a quello che digitate.
addendum basato su commenti
Dato che gli input dell'interfaccia utente rappresentano valori di stato (considera cosa succede se un utente chiude la sua scheda a metà strada e la scheda viene ripristinata. Dovrebbero essere ripristinati tutti quei valori che hanno inserito? In tal caso, quello è lo stato). Ciò potrebbe farti sentire come se un modulo di grandi dimensioni avesse bisogno di decine o anche di un centinaio di moduli di input, ma React riguarda la modellazione dell'interfaccia utente in modo sostenibile: non hai 100 campi di input indipendenti, hai gruppi di input correlati, quindi acquisisci ciascuno raggruppare in un componente e quindi creare il modulo "master" come una raccolta di gruppi.
MyForm:
render:
<PersonalData/>
<AppPreferences/>
<ThirdParty/>
...
Questo è anche molto più facile da mantenere rispetto a un componente gigante a forma singola. Suddividi i gruppi in Componenti con manutenzione dello stato, in cui ciascun componente è responsabile solo del monitoraggio di alcuni campi di input alla volta.
Potresti anche pensare che sia "una seccatura" scrivere tutto quel codice, ma si tratta di un falso risparmio: gli sviluppatori-che-non-sei-te, incluso il futuro, traggono grandi benefici dal vedere tutti quegli input collegati esplicitamente, perché rende molto più facile tracciare i percorsi del codice. Tuttavia, puoi sempre ottimizzare. Ad esempio, puoi scrivere un linker di stato
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']}/>
});
}
});
Naturalmente, ci sono versioni migliorate di questo, quindi vai su https://npmjs.com e cerca una soluzione di collegamento dello stato React che ti piace di più. L'open source riguarda principalmente la ricerca di ciò che gli altri hanno già fatto e l'utilizzo di questo invece di scrivere tutto da soli.
Reagisci 16 (e 15,5 di transizione) e JS "moderno"
A partire da React 16 (e soft-start con 15.5) la createClass
chiamata non è più supportata e deve essere utilizzata la sintassi della classe. Questo cambia due cose: la sintassi della classe ovvia, ma anche l' this
associazione del contesto che createClass
può fare "gratis", quindi per assicurarti che le cose continuino a funzionare assicurati di usare la notazione "fat arrow" per this
preservare le funzioni anonime nei onWhatever
gestori, come il onChange
che usiamo nel codice qui:
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
});
}
});
Potresti anche aver visto le persone usare bind
nel loro costruttore per tutte le loro funzioni di gestione degli eventi, come questo:
constructor(props) {
super(props);
this.handler = this.handler.bind(this);
...
}
render() {
return (
...
<element onclick={this.handler}/>
...
);
}
Non farlo.
Quasi ogni volta che stai usando bind
, si applica il proverbiale "stai sbagliando". La tua classe definisce già il prototipo dell'oggetto e quindi già definisce il contesto dell'istanza. Non aggiungere a bind
quello; utilizzare il normale inoltro di eventi invece di duplicare tutte le chiamate di funzione nel costruttore, poiché tale duplicazione aumenta la superficie del bug e rende molto più difficile tracciare gli errori perché il problema potrebbe essere nel costruttore anziché nel punto in cui si chiama il codice. Oltre a porre un onere di manutenzione sugli altri con cui (hai o scegli) lavorare.
Sì, so che i documenti di reazione dicono che va bene. Non lo è, non farlo.
Reagire 16.8, utilizzando i componenti di funzione con ganci
A partire da React 16.8 il componente della funzione (cioè letteralmente solo una funzione che accetta alcuni props
argomenti può essere usato come se fosse un'istanza di una classe componente, senza mai scrivere una classe) può anche essere dato stato, attraverso l'uso di hook .
Se non hai bisogno di un codice di classe completo, e una funzione di singola istanza lo farà, allora puoi usare l' useState
hook per ottenere una singola variabile di stato e la sua funzione di aggiornamento, che funziona più o meno come negli esempi precedenti, tranne senza la setState
chiamata di funzione:
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>
);
}
In precedenza la distinzione non ufficiale tra classi e componenti di funzione era "i componenti di funzione non hanno stato", quindi non possiamo più nasconderci dietro quello: la differenza tra componenti di funzione e componenti di classi può essere trovata diffusa su diverse pagine nel documentazione di reazione scritta (nessuna scorciatoia una spiegazione di copertina per interpretare erroneamente per te!) che dovresti leggere in modo da sapere cosa stai facendo e quindi sapere se hai scelto la soluzione migliore (qualunque cosa significhi per te) per programmare te stesso per un problema che stai riscontrando.
this.onSubmit.bind(this);