javascript - React + Redux - Hva er den beste måten å håndtere CRUD i en skjema-komponent på?
Jeg har et skjema som brukes til å Opprette, Lese, Oppdatere og Slette. Jeg laget 3 komponenter med det samme skjemaet, men jeg gir dem forskjellige props. Jeg har CreateForm.js, ViewForm.js (kun lesing med sletteknappen) og UpdateForm.js.
Jeg pleide å jobbe med PHP, så jeg gjorde alltid disse i ett skjema.
Jeg bruker React og Redux for å administrere butikken.
Når jeg er i CreateForm-komponenten, sender jeg til underkomponentene mine denne props createForm={true} for å ikke fylle feltene med en verdi og ikke deaktivere dem. I min ViewForm-komponent sender jeg denne props readonly="readonly".
Og jeg har et annet problem med et tekstområde som er fylt med en verdi og ikke kan oppdateres. React-tekstområde med verdi er skrivebeskyttet, men må kunne oppdateres
Hva er den beste strukturen for å ha bare én komponent som håndterer disse forskjellige tilstandene til skjemaet?
Har du noen råd, veiledninger, videoer, demoer å dele?
Svar #1
Jeg fant Redux Form-pakken. Den gjør en virkelig god jobb!
Så, du kan bruke Redux med React-Redux.
Først må du lage en skjema-komponent (åpenbart):
import React from 'react';
import { reduxForm } from 'redux-form';
import validateContact from '../utils/validateContact';
class ContactForm extends React.Component {
render() {
const { fields: {name, address, phone}, handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit}>
<label>Name</label>
<input type="text" {...name}/>
{name.error && name.touched && <div>{name.error}</div>}
<label>Address</label>
<input type="text" {...address} />
{address.error && address.touched && <div>{address.error}</div>}
<label>Phone</label>
<input type="text" {...phone}/>
{phone.error && phone.touched && <div>{phone.error}</div>}
<button onClick={handleSubmit}>Submit</button>
</form>
);
}
}
ContactForm = reduxForm({
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 default ContactForm;
Etter dette kobler du til komponenten som håndterer skjemaet:
import React from 'react';
import { connect } from 'react-redux';
import { initialize } from 'redux-form';
import ContactForm from './ContactForm.react';
class App extends React.Component {
handleSubmit(data) {
console.log('Submission received!', data);
this.props.dispatch(initialize('contact', {})); // clear form
}
render() {
return (
<div id="app">
<h1>App</h1>
<ContactForm onSubmit={this.handleSubmit.bind(this)}/>
</div>
);
}
}
export default connect()(App);
Og legg til redux-form reduktoren i dine kombinerte reduktorer:
import { combineReducers } from 'redux';
import { appReducer } from './app-reducers';
import { reducer as formReducer } from 'redux-form';
let reducers = combineReducers({
appReducer, form: formReducer // this is the form reducer
});
export default reducers;
Og validator-modulen ser slik ut:
export default function validateContact(data, props) {
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;
}
Etter at skjemaet er fylt ut, når du vil fylle alle feltene med noen verdier, kan du bruke initialize-funksjonen:
componentWillMount() {
this.props.dispatch(initialize('contact', {
name: 'test'
}, ['name', 'address', 'phone']));
}
En annen måte å fylle ut skjemaene på er å sette initialverdiene.
ContactForm = reduxForm({
form: 'contact', // the name of your form and the key to
fields: ['name', 'address', 'phone'], // a list of all your fields in your form
validate: validateContact // a synchronous validation function
}, state => ({
initialValues: {
name: state.user.name,
address: state.user.address,
phone: state.user.phone,
},
}))(ContactForm);
Hvis du har en annen måte å håndtere dette på, bare legg igjen en melding! Takk.
Svar #2
OPPDATERING: det er 2018 og jeg vil bare noen gang bruke Formik (eller Formik-lignende biblioteker)
Det finnes også react-redux-form (trinn for trinn), som ser ut til å bytte noe av redux-forms JavaScript (& boilerplate) med markup-deklarasjon. Det ser bra ut, men jeg har ikke brukt det ennå.
En kopier og lim fra readme-filen:
import React from 'react';
import { createStore, combineReducers } from 'redux';
import { Provider } from 'react-redux';
import { modelReducer, formReducer } from 'react-redux-form';
import MyForm from './components/my-form-component';
const store = createStore(combineReducers({
user: modelReducer('user', { name: '' }),
userForm: formReducer('user')
}));
class App extends React.Component {
render() {
return (
<Provider store={ store }>
<MyForm />
</Provider>
);
}
}
./components/my-form-component.jsimport React from 'react';
import { connect } from 'react-redux';
import { Field, Form } from 'react-redux-form';
class MyForm extends React.Component {
handleSubmit(val) {
// Do anything you want with the form value
console.log(val);
}
render() {
let { user } = this.props;
return (
<Form model="user" onSubmit={(val) => this.handleSubmit(val)}>
<h1>Hello, { user.name }!</h1>
<Field model="user.name">
<input type="text" />
</Field>
<button>Submit!</button>
</Form>
);
}
}
export default connect(state => ({ user: state.user }))(MyForm);
Rediger: Sammenligning
Dokumentasjonen for react-redux-form gir en sammenligning med redux-form:
https://davidkpiano.github.io/react-redux-form/docs/guides/compare-redux-form.html
