redux-form to bardzo interesująca biblioteka do dostarczania wiązań redux dla formularzy w aplikacji reagującej, która powinna być super-wygodna. Niestety, korzystając z własnych przykładów biblioteki, nie udaje mi się niczego powiązać, co jest super wygodne.Jak powiązać wiązania formularzy reduktorów z wejściami formularza
Próbuję użyć przykładowego kodu na stronie projektu i znaleźć wiele przeszkód, pomimo próby wiernego odtworzenia go. Gdzie błędnie interpretuję ten interfejs API? Czy interfejs API został przesunięty od czasu napisania kodu demo? Czy brakuje mi jakiejś krytycznej i oczywistej wiedzy na temat redux?
Problem 1: Podpis metody handleSubmit powinien być handleSubmit(data)
. Ale funkcja handleSubmit otrzymuje obecnie tylko komunikat React syntheticEvent z akcji przesyłania i brak danych. (W rzeczywistości, użycie napisanego na przyklad przykładu wysłało dwa osobne zdarzenia, pozornie z powodu ułożonej akcji onSubmit
na formularzu i onClick
na przycisku.) Skąd pochodzą te dane i dlaczego nie mogę tego zrobić? przekazać go do obsługi?
Problem 2: istnieje krytyczna fields
obiekt, który musi być określony na formularzu rodzica i dostarczone jako rekwizyt do formularza. Niestety, kształt tego obiektu fields
nie jest wyjaśniony w dokumentach ani w jego celu. Czy w gruncie rzeczy jest to początkowy obiekt "stanu"? Prosty kontener obiektowy dla formy redux do użycia w czasie wykonywania dla błędów itp.? Dostałem go, aby przestać robić błędy, dopasowując rekwizyty z fields
do nazw pól w connectReduxForm
, ale ponieważ dane nie są wiążące, zakładam, że nie jest to właściwy kształt.
Problem 3: Pola mają być automatycznie związana z obsługą dla onBlur
i onChange
, tak aby zaktualizować sklep odpowiednio. To się nigdy nie zdarza. (Co możemy zobaczyć dzięki dev-tools Redux Jednak handleSubmit
powodzeniem wysyłki akcję initialize
, co sugeruje, sklepu, reduktor, i inne podstawowe kanalizacja wszyscy pracujemy.).
Problem 4: validateContact
jest wypalanie raz na init, ale nigdy więcej.
Jest to niestety zbyt skomplikowane na proste Fiddle, ale całe repo (to tylko podstawowe ReduxStarterApp, plus ten formularz POC) is available here.
I tu jest zewnętrzny komponent:
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);
i wewnętrzną komponent forma:
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;
Dziękuję za to skomplikowane pytanie! Miałem te same trudności i uważam, że dokumentacja formy redux i przykłady są skomplikowane i niekompletne. Dzięki pomocy twojej i @ Jonny Buchanana mogłem kontynuować (chociaż mam skomplikowaną strukturę danych i jeszcze nie skończyłem). Dodanie rozszerzenia [redux devtools extension] (https://github.com/zalmoxisus/redux-devtools-extension) również bardzo pomogło przy debugowaniu! –