Bắt đầu với Reactjs- Phần 5, Tìm hiểu về redux-form (2)
Bài đăng này đã không được cập nhật trong 6 năm
2.2 Ví dụ:
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="width=device-width, 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ủaredux-form
làValues
Khá là tiện dụng khi debug vớisimple
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
reducesrc/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:\n\n${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 idsrc/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ả:
All rights reserved