React input defaultValue non si aggiorna con lo stato

Sto provando a creare un semplice modulo con reactjs, ma affrontando difficoltà nel far bind correttamente i dati al valore predefinito del modulo.

Il comportamento che sto cercando è questo:

  1. Quando apro la mia pagina, il campo di inserimento del testo deve essere compilato con il testo del mio AwayMessage nel mio database. Questo è “testo di esempio”
  2. Idealmente, desidero avere un segnaposto nel campo di input Testo se AwayMessage nel mio database non ha testo.

Tuttavia, al momento, sto scoprendo che il campo di input Testo è vuoto ogni volta che aggiorno la pagina. (Anche se quello che digito nell’input si salva in modo corretto e persiste.) Penso che questo sia dovuto al carico HTML del campo di testo di input quando AwayMessage è un object vuoto, ma non si aggiorna quando viene caricato il awayMessage. Inoltre, non sono in grado di specificare un valore predefinito per il campo.

Ho rimosso parte del codice per maggiore chiarezza (es. SuToggleChange)

window.Pages ||= {} Pages.AwayMessages = React.createClass getInitialState: -> App.API.fetchAwayMessage (data) => @setState awayMessage:data.away_message {awayMessage: {}} onTextChange: (event) -> console.log "VALUE", event.target.value onSubmit: (e) -> window.a = @ e.preventDefault() awayMessage = {} awayMessage["master_toggle"][email protected]["master_toggle"].getDOMNode().checked console.log "value of text", @refs["text"].getDOMNode().value awayMessage["text"][email protected]["text"].getDOMNode().value @awayMessage(awayMessage) awayMessage: (awayMessage)-> console.log "I'm saving", awayMessage App.API.saveAwayMessage awayMessage, (data) => if data.status == 'ok' App.modal.closeModal() notificationActions.notify("Away Message saved.") @setState awayMessage:awayMessage render: -> console.log "AWAY_MESSAGE", this.state.awayMessage awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else "Placeholder Text" `

Away Messages

il mio console.log per AwayMessage mostra quanto segue:

 AWAY_MESSAGE Object {} AWAY_MESSAGE Object {id: 1, company_id: 1, text: "Sample Text", master_toggle: false} 

defaultValue è solo per il carico iniziale

Se si desidera inizializzare l’input, è necessario utilizzare defaultValue, ma se si desidera utilizzare lo stato per modificare il valore, è necessario utilizzare il valore. Personalmente mi piace usare solo defaultValue se lo sto solo inizializzando e poi basta usare i riferimenti per ottenere il valore quando invio. Sono disponibili maggiori informazioni su refs e input sui documenti di risposta, https://facebook.github.io/react/docs/forms.html e https://facebook.github.io/react/docs/working-with-the- browser.html .

Ecco come vorrei riscrivere il tuo contributo:

 awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else ''  

Inoltre, non vuoi passare il testo segnaposto come hai fatto perché in realtà questo valore verrà impostato su “testo segnaposto”. È ancora necessario passare un valore vuoto nell’input perché undefined e nil convertono il valore in defaultValue in sostanza. https://facebook.github.io/react/tips/controlled-input-null-value.html .

getInitialState non può effettuare chiamate API

È necessario effettuare chiamate api dopo l’esecuzione di getInitialState. Per il tuo caso lo farei in componentDidMount. Segui questo esempio, https://facebook.github.io/react/tips/initial-ajax.html .

Raccomando anche di leggere il ciclo di vita dei componenti con reactjs. https://facebook.github.io/react/docs/component-specs.html .

Riscrivi con modifiche e stato di caricamento

Personalmente non mi piace fare il resto se non la logica nel rendering e preferisco usare il “caricamento” nel mio stato e renderizzare un filatore impressionante prima del caricamento del modulo, http://fortawesome.github.io/Font- Fantastico / esempi / . Ecco una riscrittura per mostrarti cosa intendo. Se ho incasinato le zecche per cjsx, è perché normalmente uso solo caffè come questo,.

 window.Pages ||= {} Pages.AwayMessages = React.createClass getInitialState: -> { loading: true, awayMessage: {} } componentDidMount: -> App.API.fetchAwayMessage (data) => @setState awayMessage:data.away_message, loading: false onToggleCheckbox: (event)-> @state.awayMessage.master_toggle = event.target.checked @setState(awayMessage: @state.awayMessage) onTextChange: (event) -> @state.awayMessage.text = event.target.value @setState(awayMessage: @state.awayMessage) onSubmit: (e) -> # Not sure what this is for. I'd be careful using globals like this window.a = @ @submitAwayMessage(@state.awayMessage) submitAwayMessage: (awayMessage)-> console.log "I'm saving", awayMessage App.API.saveAwayMessage awayMessage, (data) => if data.status == 'ok' App.modal.closeModal() notificationActions.notify("Away Message saved.") @setState awayMessage:awayMessage render: -> if this.state.loading `` else `

Away Messages

Questo dovrebbe coprirlo. Questo è un modo per andare sulle forms che usano lo stato e il valore. Puoi anche usare defaultValue anziché value e quindi usare refs per ottenere i valori quando invii. Se segui questa strada ti consiglio di avere un componente shell esterno (di solito indicato come componenti di alto ordine) per recuperare i dati e quindi passarli al modulo come oggetti di scena.

In generale, consiglierei di leggere i documenti di risposta fino in fondo e fare alcuni tutorial. Ci sono molti blog là fuori e http://www.egghead.io ha dei buoni tutorial. Ho alcune cose sul mio sito pure, http://www.openmindedinnovations.com .

Un altro modo per risolvere ciò è cambiando la key dell’input.

  

Aggiornamento: Dato che si otterrà l’upvotes, dovrò dire che dovresti avere un object di supporto disabled o di readonly mentre il contenuto è in fase di caricamento, in modo da non diminuire l’esperienza utente.

E sì, è più probabile che sia un hack, ma ha fatto il lavoro .. 😉

Forse non è la soluzione migliore, ma creo un componente come quello qui sotto, così posso riutilizzarlo ovunque nel mio codice. Vorrei che fosse già in reazione di default.

  

Il componente può essere simile a:

 window.MagicInput = React.createClass onChange: (e) -> state = @props.binding[0].state changeByArray state, @path(), e.target.value @props.binding[0].setState state path: -> @props.binding[1].split('.') getValue: -> value = @props.binding[0].state path = @path() i = 0 while i < path.length value = value[path[i]] i++ value render: -> type = if @props.type then @props.type else 'input' parent_state = @props.binding[0] `` 

Dove change by array è una funzione che accede all’hash da un percorso express da una matrice

 changeByArray = (hash, array, newValue, idx) -> idx = if _.isUndefined(idx) then 0 else idx if idx == array.length - 1 hash[array[idx]] = newValue else changeByArray hash[array[idx]], array, newValue, ++idx 

Il modo più affidabile per impostare i valori iniziali consiste nell’utilizzare componentDidMount () {} oltre a render () {}:

 ... componentDidMount(){ const {nameFirst, nameSecond, checkedStatus} = this.props; document.querySelector('.nameFirst').value = nameFirst; document.querySelector('.nameSecond').value = nameSecond; document.querySelector('.checkedStatus').checked = checkedStatus; return; } ... 

Potresti trovare facile distruggere un elemento e sostituirlo con quello nuovo con

  

come questo:

 if(document.querySelector("#myParentElement")){ ReactDOM.unmountComponentAtNode(document.querySelector("#myParentElement")); ReactDOM.render( , document.querySelector("#myParentElement") ); }; 

Puoi utilizzare anche questa versione del metodo di sassembly:

 ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode); 

sebbene non consigliato da reactjs, funziona:

 render() { const { value } = this.state; return ; } 

Dare valore al parametro “placeHolder”. Per esempio :-