Il motivo tecnico è che nel momento in cui si tenta di accedere al componente figlio, non esistono ancora realmente (nel DOM). Non sono ancora stati montati. Sono stati passati al componente <Form>
come prop o metodo del costruttore come risposta classe. (da cui la classe nome in React.createClass()
).
Come si fa notare, questo può essere aggirato utilizzando i riferimenti, ma non lo consiglierei. In molti casi, i ref tendono a essere scorciatoie per qualcosa a cui reagire non era destinato, e quindi dovrebbero essere evitati.
È probabile che, in base alla progettazione, la reazione impedisca ai genitori di accedere ai metodi di un bambino. Non dovrebbero. I metodi del bambino dovrebbero essere nel bambino se sono privati del bambino: fanno qualcosa all'interno del bambino che non dovrebbe essere comunicato direttamente al genitore. Se così fosse, allora la manipolazione avrebbe dovuto essere fatta all'interno del genitore. Perché il genitore ha almeno tutte le informazioni e i dati del bambino.
Ora, nel tuo caso, immagino che ogni componente di input (figlio) abbia un qualche tipo di metodo di convalida specifico, che controlli il valore di input e, in base al risultato, restituisca un messaggio di errore. Diciamo un contorno rosso attorno ai campi errati.
Nel modo reagire, ciò potrebbe essere ottenuto come segue:
- componente
<Form>
ha stato, che comprende un booleano runValidation
.
- non appena
runValidation
è impostato su true, all'interno di una risposta setState({ runValidation: true });
viene eseguito automaticamente il rendering di tutti i bambini.
- se si include
runValidation
come sostegno per tutti i bambini.
- poi ogni bambino può controllare all'interno della loro funzione
render()
con qualcosa di simile if (this.props.runValidation) { this.validate() }
- che eseguirà la funzione
validate()
nel bambino
- la funzione di convalida può anche utilizzare lo stato del bambino (lo stato non viene modificato quando i nuovi oggetti di scena sono disponibili in), e usa quello per il messaggio di convalida (es. "aggiungi simboli più complicati alla tua password")
Ora, ciò che non risolve ancora, è che potresti voler fare un controllo a livello di modulo dopo tutto i bambini si sono convalidati: es quando tutti i bambini sono OK, invia il modulo.
Per risolvere ciò, è possibile applicare la scorciatoia di riferimento al controllo finale e inviare. E implementa un metodo nel tuo <Form>
all'interno di una funzione componentDidUpdate()
, per verificare se ogni bambino è OK (ad esempio ha un bordo verde) E se l'invio è cliccato, e quindi invia. Ma come regola generale, consiglio vivamente di non usare i ref.
Per la convalida forma finale, un approccio migliore è:
- aggiungere una variabile non statale all'interno della vostra
<Form>
che detiene booleani per ogni bambino. NB, deve essere non-stato, per impedire ai bambini di attivare un nuovo ciclo di rendering.
- passare una funzione
validateForm
come un puntello (callback) per ogni bambino.
- all'interno di
validate()
in ogni bambino, chiamare this.props.validateForm(someChildID)
che aggiorna il valore booleano corrispondente nella variabile nel modulo.
- alla fine della funzione
validateForm
nel modulo, controllare se tutti i valori booleani sono veri e, in tal caso, inviare il modulo (o modificare lo stato del modulo o qualsiasi altra cosa).
Per una soluzione ancora più lunga (e molto più complicata) per formare la convalida in risposta (con flusso) è possibile controllare this article.
Perché una variabile per la convalida deve essere una variabile non di stato? –
Perché non si desidera eseguire nuovamente il rendering del modulo quando ogni bambino riporta "Ok" o "non Ok", ovvero cosa succederebbe se lo si inserisse nello stato modulo. Si desidera solo avere lo stato per il modulo completo e modificare lo stato/ri-rendering solo se tutti i bambini sono OK. – wintvelt