2015-10-15 14 views
28

redux-form è una libreria molto convincente per fornire binding redux per moduli in un'applicazione di risposta, che dovrebbe essere super-conveniente. Sfortunatamente, usando gli esempi propri della libreria, non riesco a legare effettivamente nulla, il che è super-conveniente.Come collegare collegamenti redux-form agli input del modulo

Sto tentando di utilizzare il codice di esempio sul sito del progetto e di trovare ostacoli multipli, nonostante il tentativo di riprodurlo fedelmente. Dove sto interpretando erroneamente questa API? L'API è stata spostata da quando è stato scritto il codice demo? Mi manca qualche pezzo critico e ovvio di conoscenza redux?

Problema 1: la firma per il metodo handleSubmit deve essere handleSubmit(data). Ma handleSubmit sta attualmente ricevendo solo React syntheticEvent dall'azione di invio e nessun dato. (In effetti, l'utilizzo dell'esempio scritto stava inviando due eventi separati, apparentemente a causa dell'azione impilata onSubmit sul modulo e dello onClick sul pulsante.) Da dove provengono i dati e perché non riesco a passarlo al gestore?

Problema 2: è presente un oggetto critico fields che deve essere definito nel modulo padre e fornito come elemento di supporto al modulo. Sfortunatamente, la forma di quell'oggetto fields non è spiegata nei documenti, né il suo scopo, in realtà. È essenzialmente l'oggetto "stato" iniziale? Un semplice contenitore di oggetti per redux-form da utilizzare in fase di esecuzione per errori, ecc.? Ho ottenuto di smettere di errore abbinando i puntelli su fields ai nomi dei campi in connectReduxForm, ma poiché i dati non sono vincolanti, presumo che non sia la forma giusta.

Problema 3: I campi si suppone essere auto-bound per i gestori per onBlur e onChange, in modo da aggiornare l'archivio in modo appropriato. Non sta mai succedendo. (Quale possiamo vedere grazie alle Redux dev-tools Tuttavia, handleSubmit sta inviando con successo l'azione initialize, che suggerisce il negozio, riduttore, e altri installatori base sono tutti al lavoro..)

Problema 4: validateContact è sparando una volta su init, ma mai più.

Questo è sfortunatamente troppo complesso per un semplice Fiddle, ma l'intero repo (è solo il ReduxStarterApp di base, più questo modulo POC) is available here.

E, qui è la componente esterna:

import React  from 'react'; 
import { connect } from 'react-redux'; 
import {initialize} from 'redux-form'; 

import ContactForm from '../components/simple-form/SimpleForm.js'; 

const mapStateToProps = (state) => ({ 
    counter : state.counter 
}); 
export class HomeView extends React.Component { 
    static propTypes = { 
    dispatch : React.PropTypes.func.isRequired, 
    counter : React.PropTypes.number 
    } 

    constructor() { 
    super(); 
    } 
    handleSubmit(event, data) { 
    event.preventDefault(); 
    console.log(event); // this should be the data, but is an event 
    console.log(data); // no data here, either... 
    console.log('Submission received!', data); 
    this.props.dispatch(initialize('contact', {})); // clear form: THIS works 
    return false; 
    } 

    _increment() { 
    this.props.dispatch({ type : 'COUNTER_INCREMENT' }); 
    } 


    render() { 
    const fields = { 
     name: '', 
     address: '', 
     phone: '' 
    }; 

    return (
     <div className='container text-center'> 
     <h1>Welcome to the React Redux Starter Kit</h1> 
     <h2>Sample Counter: {this.props.counter}</h2> 
     <button className='btn btn-default' 
       onClick={::this._increment}> 
      Increment 
     </button> 
     <ContactForm handleSubmit={this.handleSubmit.bind(this)} fields={fields} /> 
     </div> 
    ); 
    } 
} 

export default connect(mapStateToProps)(HomeView); 

e la componente forma interna:

import React, {Component, PropTypes} from 'react'; 
import {connectReduxForm} from 'redux-form'; 

function validateContact(data) { 
    console.log("validating"); 
    console.log(data); 
    const errors = {}; 
    if (!data.name) { 
    errors.name = 'Required'; 
    } 
    if (data.address && data.address.length > 50) { 
    errors.address = 'Must be fewer than 50 characters'; 
    } 
    if (!data.phone) { 
    errors.phone = 'Required'; 
    } else if (!/\d{3}-\d{3}-\d{4}/.test(data.phone)) { 
    errors.phone = 'Phone must match the form "999-999-9999"'; 
    } 
    return errors; 
} 

class ContactForm extends Component { 
    static propTypes = { 
    fields: PropTypes.object.isRequired, 
    handleSubmit: PropTypes.func.isRequired 
    } 

    render() { 
    const { fields: {name, address, phone}, handleSubmit } = this.props; 
    return (
     <form onSubmit={handleSubmit}> 
     <label>Name</label> 
     <input type="text" {...name}/>  {/* will pass value, onBlur and onChange */} 
     {name.error && name.touched && <div>{name.error}</div>} 

     <label>Address</label> 
     <input type="text" {...address}/> {/* will pass value, onBlur and onChange*/} 
     {address.error && address.touched && <div>{address.error}</div>} 

     <label>Phone</label> 
     <input type="text" {...phone}/> {/* will pass value, onBlur and onChange */} 
     {phone.error && phone.touched && <div>{phone.error}</div>} 

     <button type='submit'>Submit</button> 
     </form> 
    ); 
    } 
} 

// apply connectReduxForm() and include synchronous validation 
ContactForm = connectReduxForm({ 
    form: 'contact',      // the name of your form and the key to 
             // where your form's state will be mounted 
    fields: ['name', 'address', 'phone'], // a list of all your fields in your form 
    validate: validateContact    // a synchronous validation function 
})(ContactForm); 

// export the wrapped component 
export default ContactForm; 
+1

Grazie per questa domanda elaborato! Ho avuto le stesse difficoltà e trovo la documentazione redux-form e gli esempi intricati e incompleti. Con il tuo aiuto di @Jonny Buchanan sono riuscito a procedere (anche se ho una complicata struttura dei dati e non ho ancora finito). Anche l'aggiunta dell'estensione [redux devtools] (https://github.com/zalmoxisus/redux-devtools-extension) ha aiutato molto il debugging! –

risposta

23

connectReduxForm avvolge il componente con un altro componente che gestisce il passaggio nelle fields e handleSubmit oggetti di scena, ma li stai soffiando passandoli in te stesso.

Prova a modificare (rinominato il puntello per onSubmit):

<ContactForm onSubmit={this.handleSubmit.bind(this)}/> 

E in ContactForm, pass your own submit handler to the handleSubmit function provided by redux-form:

<form onSubmit={handleSubmit(this.props.onSubmit)}> 

mi consiglia di utilizzare il React developer tools per avere un quadro più preciso di quello che sta succedendo - vedrai come il modulo redux avvolge il tuo componente e passes it a whole bunch of props, as documented in its README.

redux-form composition in React developer tools

+2

Potresti aggiornare il link? Tutti i collegamenti puntano alla home page github 'redux-form' ora. – Mithril

8

Grazie a Jonny Buchanan, che ha coperto il punto più importante: non fare come ho fatto io e scontato che se sono necessari puntelli nel componente, è necessario bisogno di fornire loro stessi. L'intero punto della funzione di ordine superiore che è connectReduxForm consiste nel fornirli nel componente wrapper. Correzione che mi ha dato immediatamente gestori di eventi, per tutto tranne Invia.

L'altra svista critica era qui:

NOTA - Se non si sta facendo la connect() ing te stesso (e si consiglia di non fare, a meno che non si dispone di un caso d'uso avanzato che lo richiede), è necessario montare il riduttore su modulo.

Non ho capito il punto. Ma, l'implementazione è qui:

import { createStore, combineReducers } from 'redux'; 
import { reducer as formReducer } from 'redux-form'; 
const reducers = { 
    // ... your other reducers here ... 
    form: formReducer   // <---- Mounted at 'form' 
} 
const reducer = combineReducers(reducers); 
const store = createStore(reducer); 

Il formReducer non può fare riferimento a formReducer, ma richiede la sintassi form: formReducer. Questa era la correzione che abilitava correttamente handleSubmit.

Problemi correlati