12/08/2018, 17:17
Bắt đầu với Reactjs- Phần 5, Tìm hiểu về redux-form (2)
2.2.1 Simple form: Một ví dụ cơ bản với form đăng ký gồm text field, email, textarea: Chuẩn bị file public/index.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="awidth=device-awidth, initial-scale=1, ...
2.2.1 Simple form:
-
Một ví dụ cơ bản với form đăng ký gồm text field, email, textarea:
-
Chuẩn bị file public/index.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="awidth=device-awidth, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <title>React App</title> <link rel="stylesheet" type="text/css" href="https://opensource.keycdn.com/fontawesome/4.7.0/font-awesome.min.css" media="all"> <link rel="stylesheet" type="text/css" href="https://redux-form.com/6.6.2/bundle.css" media="all"> </head> <body> <div id="root"></div> </body> </html>
- root file ở src/index.js, Ở đây mình sẽ sử dụng 1 thẻ của redux-form là Values Khá là tiện dụng khi debug với simple là form id
import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; import { Values } from "redux-form-website-template"; import store from "./store"; import showResults from "./showResults"; import SimpleForm from "./SimpleForm"; const rootEl = document.getElementById("root"); ReactDOM.render( <Provider store={store}> <div style={{ padding: 15 }}> <h2>Simple Form</h2> <SimpleForm onSubmit={showResults} /> <Values form="simple" /> </div> </Provider>, rootEl );
- Tạo store với khai báo redux-form reduce src/store.js
import { createStore, combineReducers } from 'redux'; import { reducer as reduxFormReducer } from 'redux-form'; const reducer = combineReducers({ form: reduxFormReducer, }); const store = (window.devToolsExtension ? window.devToolsExtension()(createStore) : createStore)(reducer); export default store;
- Mình muốn mở alert để show data sau khi form submit với data valid:
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); export default (async function showResults(values) { await sleep(500); window.alert(`You submitted: ${JSON.stringify(values, null, 2)}`); });
- Và đây sẽ là form của chúng ta, đầu tiên khai báo form bọc bởi high level components reduxForm và đặt cho nó 1 form id. Ở đây mình đặt là simple tên này phải nên là uniq trong ứng dụng của bạn vì form sẽ nhận lại props thông qua form id này. <=> bạn cũng có thể lợi dụng lại đặc tính này để tận dụng formRecuce của mình 1 cách tối ưu.
src/SimpleForm.js
import React from 'react'; import { reduxForm } from 'redux-form'; const SimpleForm = props => { const { handleSubmit, pristine, reset, submitting } = props; return ( <form onSubmit={handleSubmit}> </form> ); }; export default reduxForm({ form: 'simple', })(SimpleForm);
- Như ví dụ trước, ta thêm các Field component vào:
<div> <label>First Name</label> <div> <Field name="firstName" component="input" type="text" placeholder="First Name" /> </div> </div>
src/SimpleForm.js
import React from 'react'; import { Field, reduxForm } from 'redux-form'; const SimpleForm = props => { const { handleSubmit, pristine, reset, submitting } = props; return ( <form onSubmit={handleSubmit}> <div> <label>First Name</label> <div> <Field name="firstName" component="input" type="text" placeholder="First Name" /> </div> </div> <div> <label>Last Name</label> <div> <Field name="lastName" component="input" type="text" placeholder="Last Name" /> </div> </div> <div> <label>Email</label> <div> <Field name="email" component="input" type="email" placeholder="Email" /> </div> </div> <div> <label>Sex</label> <div> <label> <Field name="sex" component="input" type="radio" value="male" /> {' '} Male </label> <label> <Field name="sex" component="input" type="radio" value="female" /> {' '} Female </label> </div> </div> <div> <label>Favorite Color</label> <div> <Field name="favoriteColor" component="select"> <option /> <option value="ff0000">Red</option> <option value="00ff00">Green</option> <option value="0000ff">Blue</option> </Field> </div> </div> <div> <label htmlFor="employed">Employed</label> <div> <Field name="employed" id="employed" component="input" type="checkbox" /> </div> </div> <div> <label>Notes</label> <div> <Field name="notes" component="textarea" /> </div> </div> <div> <button type="submit" disabled={pristine || submitting}>Submit</button> <button type="button" disabled={pristine || submitting} onClick={reset}> Clear Values </button> </div> </form> ); }; export default reduxForm({ form: 'simple', })(SimpleForm);
và đơn giarn, đâu là kết quả:
2.2.2 Synchronous validation form
-
Bắt đầu chuẩn bị gần như tương tự với Simple Form
-
Ở đây mình sẽ thay đổi 1 tí ở file src/index.js thay đổi forn id src/index.js
import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "react-redux"; import { Values } from "redux-form-website-template"; import store from "./store"; import showResults from "./showResults"; import SyncValidationForm from "./SyncValidationForm"; const rootEl = document.getElementById("root"); ReactDOM.render( <Provider store={store}> <div style={{ padding: 15 }}> <h2>Synchronous Validation</h2> <SyncValidationForm onSubmit={showResults} /> <Values form="syncValidation" /> </div> </Provider>, rootEl );
- Tạo 1 component để đưa vào component Field để Show các error 1 cách cụ thể:
const renderField = ({ input, label, type, meta: { touched, error, warning } }) => ( <div> <label>{label}</label> <div> <input {...input} placeholder={label} type={type}/> {touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))} </div> </div> )
- 1 ví dụ về validate nên mình sẽ tạo 1 method validate
const validate = values => { const errors = {} if (!values.username) { errors.username = 'Required' } else if (values.username.length > 15) { errors.username = 'Must be 15 characters or less' } if (!values.email) { errors.email = 'Required' } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(values.email)) { errors.email = 'Invalid email address' } if (!values.age) { errors.age = 'Required' } else if (isNaN(Number(values.age))) { errors.age = 'Must be a number' } else if (Number(values.age) < 18) { errors.age = 'Sorry, you must be at least 18 years old' } return errors }
- Thêm 1 thông báo warnings nữa cho có vẻ nguy hiểm
const warn = values => { const warnings = {} if (values.age < 19) { warnings.age = 'Hmm, you seem a bit young...' } return warnings }
- Các mà chúng ta sẽ phải khai báo với reduxForm
export default reduxForm({ form: 'syncValidation', validate, warn })(SyncValidationForm)
src/SyncValidationForm.js
import React from 'react' import { Field, reduxForm } from 'redux-form' import React from 'react' import { Field, reduxForm } from 'redux-form' const validate = values => { const errors = {} if (!values.username) { errors.username = 'Required' } else if (values.username.length > 15) { errors.username = 'Must be 15 characters or less' } if (!values.email) { errors.email = 'Required' } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i.test(values.email)) { errors.email = 'Invalid email address' } if (!values.age) { errors.age = 'Required' } else if (isNaN(Number(values.age))) { errors.age = 'Must be a number' } else if (Number(values.age) < 18) { errors.age = 'Sorry, you must be at least 18 years old' } return errors } const warn = values => { const warnings = {} if (values.age < 19) { warnings.age = 'Hmm, you seem a bit young...' } return warnings } const renderField = ({ input, label, type, meta: { touched, error, warning } }) => ( <div> <label>{label}</label> <div> <input {...input} placeholder={label} type={type}/> {touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))} </div> </div> ) const SyncValidationForm = (props) => { const { handleSubmit, pristine, reset, submitting } = props return ( <form onSubmit={handleSubmit}> <Field name="username" type="text" component={renderField} label="Username"/> <Field name="email" type="email" component={renderField} label="Email"/> <Field name="age" type="number" component={renderField} label="Age"/> <div> <button type="submit" disabled={submitting}>Submit</button> <button type="button" disabled={pristine || submitting} onClick={reset}>Clear Values</button> </div> </form> ) } export default reduxForm({ form: 'syncValidation', validate, warn })(SyncValidationForm)
đây làm kết quả: