This section
Classroom goal
Using ant – Design
The official website
Common mode
download
npm install antd --save
Copy the code
Modify SRC/app.js to introduce antD button component.
import React, { Component } from 'react';
import Button from 'antd/es/button';
import './App.css';
import 'antd/dist/antd.css'
class App extends Component {
render() {
return (
<div className="App">
<Button type="primary">Button</Button>
</div>); }}export default App;
Copy the code
Modify SRC/app.css to introduce ANTd /dist/ antD.css at the top of the file.
Advanced configuration
The configuration above is not very friendly and can cause a lot of problems in real development. For example, the loading style above loads the entire style
At this point we need to use react-app-rewired(a community solution for custom configuration of create-React-app). Introduce react-app-rewired and modify the startup configuration in package.json. Thanks to the new [email protected] version, you’ll also need to install customize-cra.
npm i react-app-rewired customize-cra babel-plugin-import --save-dev
Copy the code
Modify the package.json startup file
"scripts": {
"start": "react-app-rewired start"."build": "react-app-rewired build"."test": "react-app-rewired test"."eject": "react-app-rewired eject"
},
Copy the code
Then create a config-overrides. Js file in the project root directory to modify the default configuration
Babel-plugin-import is a Babel plug-in for loading component code and styles on demand
const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd'.libraryDirectory: 'es'.style: 'css',}));Copy the code
Modify the App. Js
// import Button from 'antd/es/button';
// import 'antd/dist/antd.css'
import { Button } from 'antd';
Copy the code
run
npm start
Copy the code
Smart components vs. dumb components
The basics: The smart component (container component) is responsible for fetching data, and the dumb component (presentation component) is responsible for displaying information content according to props
Advantage:
- Separation of logic and content presentation
- High reusability
- High reusability
- Easy to test
In CommentList. Js
import React, {
Component
} from 'react';
function Comment({ comment }) {
console.log('render');
return (
<div>
<p>{comment.id}</p>
<p>{comment.content}</p>
<p>{comment.author}</p>
</div>)}class CommentList extends Component {
constructor(props) {
super(props);
this.state = {
comments: []}}componentDidMount() {
// Get data
setTimeout(() = > {
this.setState({
comments: [{id: 1.content: 'React is very good'.author: 'facebook'
},
{
id: 2.content: 'Vue is better than you'.author: 'Yu Yu Creek'}]})},1000);
}
render() {
return (
<div>
{
this.state.comments.map((item, i) => (
<Comment comment={item} key={item.id} />))}</div>); }}export default CommentList;
Copy the code
A presentation component prints render twice, because there are two sets of data and render twice
I now do a rotation and update the data every second
// Start updating every 1 second
setInterval(() = > {
this.setState({
comments: [{id: 1.content: 'React is very good'.author: 'facebook'
},
{
id: 2.content: 'Vue is better than you'.author: 'Yu Yu Creek'}]})},1000);
Copy the code
You’ll notice that every time the render is printed, the dumb component is re-rendered
Think: The data hasn’t changed, do I need to update it? Even though React is smart, it’s going to be a diff algorithm comparison between them, which is a performance drain
Solution 1: use shouldComponentUpdate
Extend COMMENT into a class component and define the following methods
shouldComponentUpdate(nextProps){
if(nextProps.comment.id === this.props.comment.id){
// return false indicates no update
return false;
}else{
return true; }}Copy the code
Solution 2: Use React.PureComponent
React.purecomponent is similar to sholdComponentUpdate(). The difference is that the react. PureComponent does not implement shonldComponentUpdate(). Instead, the React.PureComponent implements this function in a shallow comparison of prop and state
If the object contains complex data structures, it is possible to produce incorrect alignment results because deep differences cannot be examined. Use React.PureComponent only if your props and state are simple
Modify CommentList. Js
render() {
return (
<div>
{/* {
this.state.comments.map((item, i) => (
<Comment id={item.id} content={item.content} author={item.author} key={item.id} />)) * /}} {/ * or you can write *} {this.state.com ments. The map ((item, I) = > (<Comment {. item} key={item.id} />))}</div>
);
}
Copy the code
Modify the Comment. Js
class Comment extends PureComponent{
constructor(props) {
super(props);
}
render() {
console.log('render');
return (
<div>
<p>{this.props.id}</p>
<p>{this.props.content}</p>
<p>{this.props.author}</p>
</div>)}}Copy the code
Solution 3: Use React. Memo
React.memo is a higher-order component. It is very similar to the React.PureComponent, but it applies to function components, not class components.
const Comment = React.memo(({id,content,author}) = >{
return (
<div>
<p>{id}</p>
<p>{content}</p>
<p>{author}</p>
</div>)})Copy the code
Modify CommentList. Js
class CommentList extends Component{
render() {
return (
<div>
{
this.state.comments.map((item, i) => (
<Comment id={item.id} content={item.content} author={item.author} key={item.id} />))}</div>); }}Copy the code
Component composition rather than inheritance
The official quote is this:
React has a very powerful combination mode. We recommend using composition rather than inheritance to achieve code reuse between components.
/components/Compond.js
import React, { Component } from 'react';
import {
Button
} from "antd";
function Dialog(props) {
return (
<div style={{ border: `3px solidThe ${props.color| | 'blue` '}}} >{/* Equivalent to: vue anonymous socket */} {props. Children} {/* named socket */}<div>
{props.btn}
</div>
</div>)}// Pass any component as a child
function WelcomeDialog() {
const confirmBtn = <Button type='primary' onClick={()= >{alert('react really good ')}}> Confirm</Button>
return (
<Dialog color='green' btn={confirmBtn}>
<h3>welcome</h3>
<p>welcome</p>
</Dialog>)}class Compound extends Component {
render() {
return (
<div>
<WelcomeDialog />
</div>); }}export default Compound;
Copy the code
High order component
The purpose of component design is to ensure the simplicity of component function
// Higher-order componentsA function that receives a component and returns a new component Comment is like: I give you a Saiyan, you give me a super Saiyan// Higher order functionDefinition: receive arguments that are functions or return values that are common to functions: array traversal related methods, timers,Promise/ Advanced component role: to achieve a more powerful, dynamic functionCopy the code
Higher-order Component (HOC) is an advanced technique used in React to reuse component logic. HOC itself is not part of the React API; it is a design pattern based on the composite features of React.
Specifically, a higher-order component is a function that takes a component and returns a new component
/components/Hoc.js
const HightOrderCom = (Comp) = > {
// Returns a new component
const NewComponent = function (props) {
return <Comp name='react' content='Use of Advanced Components' {. props} ></Comp>
}
return NewComponent;
}
Copy the code
The HightOrderCom component above, in effect, proxies Comp by passing in the name and content parameters
import React, { Component } from 'react'
function MyNormalCom(props) {
return (
<div>
<p>Class name :{props. Name}</p>
<h3>{props. Content}</h3>
</div>)}// Advanced components
const HighOrderCom = (Comp) = > {
return (props) = >{
return <Comp name='react' content='Use of higher-order components' {. props} ></Comp>}}export default HighOrderCom(MyNormalCom);
Copy the code
Overrides the internal lifecycle of higher-order components
const HightOrderCom = (Comp) = > {
// Returns a new component
return class extends Component {
constructor(props) {
super(props)
}
componentDidMount(){
console.log('Make an Ajax request');
}
render() {
return (
<Comp name='react' content='Use of Advanced Components' {. this.props} ></Comp>); }}}Copy the code
Higher-order component chain calls
// A higher-order component that prints logs
const WithLog = (Comp) = >{
console.log(Comp.name + 'Rendered');
const MyComponent = function(props) {
return <Comp {. props} ></Comp>
}
return MyComponent;
}
Copy the code
Call:
const HOC = HightOrderCom(WithLog(WithLog(MyNormalCom)));
Copy the code
High order component decorator writing
While the chain-writing is a pain in the neck and the logic is convoluted, ES7 has an excellent syntax for dealing with this problem: decorator
cnpm install --save-dev babel-plugin-transform-decorators-legacy @babel/plugin-proposal-decorators
Copy the code
Configuration modification:
const {
override,
fixBabelImports, // Load configuration functions on demand
addBabelPlugins // Babel plug-in configuration function
} = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
addBabelPlugins( // Support decorators
[
'@babel/plugin-proposal-decorators',
{
legacy: true}]));Copy the code
const HightOrderCom = (Comp) = > {
// Returns a new component
return class extends Component {
constructor(props) {
super(props)
}
componentDidMount() {
console.log('Make an Ajax request');
}
render() {
return (
<Comp name='react' content='Use of Advanced Components' {. this.props} ></Comp>); }}}// A higher-order component that prints logs
const WithLog = (Comp) = > {
console.log(Comp.name + 'Rendered');
const MyComponent = function (props) {
return <Comp {. props} ></Comp>
}
return MyComponent;
}
@withLog
@HighOrderCom
@withLog
class Hoc extends Component {
constructor(props){
super(props);
}
render() {
return (
<div>
<p>Class name :{this.props. Name}</p>
<h3>{this.props. Content}</h3>
</div>); }}export default Hoc;
Copy the code
Resolve red warnings in vscode
Find the gear button in the lower left corner of the editor and click the button to find the Settings. You will be presented with two interfaces: 1. Enter experimental decorators on the edit screen and check the box shown
Advanced component applications
Access control
The conditional rendering feature of higher-order components can be used to control page permissions
/components/HocApp.js
import React, { Component } from 'react'
// Permission control
// Technology that doesn't talk about the scene is playing hooligan
export const withAdminAuth = (role) = > (WrappedComp) = > {
return class extends Component {
constructor(props) {
super(props);
this.state = {
isAdmin: false}}componentDidMount() {
setTimeout(() = > {
this.setState({
isAdmin: role === 'Admin'})},1000);
}
render() {
if (this.state.isAdmin) {
return (
<WrappedComp {. this.props} ></WrappedComp>
);
} else {
return (
<div>You do not have permission to view this page, please contact the administrator</div>)}}}}Copy the code
Then there are two pages:
/components/PageA.js
import React, { Component } from 'react'
import { withAdminAuth } from "./HocApp";
class PageA extends Component {
componentDidMount() {
setTimeout(() = > {
this.setState({
isAdmin: true})},1000);
}
render() {
return (
<div>
<h2>I'm page A</h2>
</div>)}}export default withAdminAuth('Admin')(PageA)
Copy the code
/components/PageB.js
import React, { Component } from 'react'
import { withAdminAuth } from "./HocApp";
class PageB extends Component {
render() {
return (
<div>
<h2>I'm page B</h2>
</div>)}}export default withAdminAuth()(PageB);
Copy the code
Page A can be accessed, but page B cannot be accessed
Page reuse
Component Communication Context
Context provides a way to pass data across the component tree without manually adding props for each layer of components.
In a typical React application, data is passed top-down (from parent to child) through the props properties, but this is extremely cumbersome for certain types of properties (e.g. locale preferences, UI themes) that are required by many components in the application. Context provides a way to share such values between components without explicitly passing props layer by layer through the component tree.
When to use Context
Context is designed to share global data, such as the currently authenticated user, topic, and so on. Here’s an example:
import React, { Component } from 'react';
// Context allows us to go through each component and push values deeper into the component tree
// Create a ThemeContext with the default value light
const ThemeContext = React.createContext('lighter');
class ThemeButton extends Component {
// Specify contextType to read the current theme context.
// React will find the nearest theme Provider and use its value.
// In this case, the current theme value is "dark".
Static contextType = ThemeContext; static contextType = ThemeContext;
render() {
return (
// <button type={this.context}></button>
<ThemeContext.Consumer>{/* 2. Render value based on function equivalent to this.context */} {value =><button theme={value.theme}>{value.name}</button>
}
</ThemeContext.Consumer>); }}function Toolbar(props) {
// The Toolbar component accepts an additional "theme" property, which is passed to the ThemedButton component.
// If every single button in your application needs to know the theme value, this would be a hassle,
// Because this value must be passed layer by layer to all components.
return (
<div>
<ThemeButton></ThemeButton>
</div>)}// The data passed
const store = {
theme:'dark'.name:'button'
}
class ContextSimple extends Component {
// Use the Provider to push the current value='dark' into the component tree so that any component can read the value, no matter how deep
render() {
return (
<div>
<ThemeContext.Provider value={store}>
<Toolbar></Toolbar>
</ThemeContext.Provider>
</div>); }}export default ContextSimple;
Copy the code
High order component decorator writing
import React, { Component } from 'react';
const ThemeContext = React.createContext('lighter');
const withConsumer = Comp= > {
return class extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ThemeContext.Consumer>
{
value => <Comp {. this.props} value={value}></Comp>
}
</ThemeContext.Consumer>
);
}
}
}
@withConsumer
class ThemeButton extends Component {
constructor(props) {
super(props);
}
render() {
return (
<button theme={this.props.value.theme}>{this.props.value.name}</button>); }}function Toolbar(props) {
return (
<div>
<ThemeButton></ThemeButton>
</div>)}// The data passed
const store = {
theme: 'dark'.name: 'button'
}
const withProvider = Comp= > {
return function (props) {
return (
<ThemeContext.Provider value={store}>
<Comp {. props} / >
</ThemeContext.Provider>
)
}
}
@withProvider
class ContextSimple extends Component {
render() {
return (
<div>
<Toolbar></Toolbar>
</div>); }}export default ContextSimple;
Copy the code
Encapsulate antD’s form form
Go to antD’s official website
import React from 'react'
import { Form, Icon, Input, Button } from 'antd';
function hasErrors(fieldsError) {
return Object.keys(fieldsError).some(field= > fieldsError[field]);
}
class HorizontalLoginForm extends React.Component {
componentDidMount() {
// To disabled submit button at the beginning.
this.props.form.validateFields();
}
handleSubmit = e= > {
e.preventDefault();
this.props.form.validateFields((err, values) = > {
if(! err) {console.log('Received values of form: ', values); }}); };render() {
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
// Only show error after a field is touched.
const usernameError = isFieldTouched('username') && getFieldError('username');
const passwordError = isFieldTouched('password') && getFieldError('password');
return (
<Form layout="inline" onSubmit={this.handleSubmit}>
<Form.Item validateStatus={usernameError ? 'error' :"'}help={usernameError| | '} >
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0.0.0.25.) '}} / >}
placeholder="Username"
/>,
)}
</Form.Item>
<Form.Item validateStatus={passwordError ? 'error' :"'}help={passwordError| | '} >
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input
prefix={<Icon type="lock" style={{ color: 'rgba(0.0.0.25.) '}} / >}
type="password"
placeholder="Password"
/>,
)}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" disabled={hasErrors(getFieldsError())}>
Log in
</Button>
</Form.Item>
</Form>); }}const WrappedHorizontalLoginForm = Form.create({ name: 'horizontal_login' })(HorizontalLoginForm);
ReactDOM.render(<WrappedHorizontalLoginForm />, mountNode);
Copy the code
Component function analysis
- Each input box is triggered to perform a non-null check with an error
- Verify the form items when submitting the form. If the verification succeeds, login will be prompted; otherwise, verification failure will be prompted
- Form items have front ICONS
Component Encapsulation
- You need a higher-order function HOC,
MFormCreate
, mainly responsible for packaging user forms and increasing data management ability; It needs to extend four features:getFieldDecorator, getFieldsError, getFieldError, isFieldTouched
. Gets the field wrapper methodgetFieldDecorator
The return value of is an advanced function that takes an Input component as an argument and returns a new component. This is to turn an ordinary form item into a form item with extended functionality (for example, adding validation rules for that item). - The FormItem component is responsible for displaying checksum and error information. It needs to save two properties, the checksum status and error information. The error information is empty when the checksum is passed
- Input component, display component, add Input box front icon
- Export the MForm component decorated with MFormCreate, which is responsible for style layout and submission control
Component packaging Steps
- Complete a basic component MForm, page display
- Write a higher-order component MFormCreate to extend MForm, so that THE MForm component has the ability to manage data.
- Save field options set this.options = {}; We don’t need to save state here because we don’t want the field options to change and the component to be re-rendered
- Save the value of each field this.state = {}
- Define the method getFieldDecorator()(), passing the configuration item as the first argument and the Input component as the second argument; The first parameter includes the current verification item and verification rule
'username',{rules:[require:true,message:' enter username']}
- In MFormCreate, clone an Input component and define the onChange event for the Input. First, we need to clone the existing JSX and modify its properties. It is not allowed to modify the properties directly. Here the onChange event is defined at a higher level to control the value of the element so that there is no communication back and forth between components when they change. The data changes are left to the container component, and the lower-level component is only responsible for presentation.
- Added the submission verification function
- Add FormItem component to perform real-time verification and prompt error message after the FormItem is triggered
MForm.js
import React, { Component } from 'react';
class MForm extends Component {
render() {
return (
<div>
<input type="text" />
<input type="password"/>
<input type="submit" value='login'/>
</div>); }}export default MForm;
Copy the code
Extend the MForm component with the higher-order component MFormCreate; Display validation error information through the FormItem component
import React, { Component } from 'react';
// Wrap the user form, add data management capability and validation function
const MFormCreate = function (Comp) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};// Save the values of each field
this.options = {}; // Save the field option setting does not want it to change to let the component render
}
// Process the form entry event
handlerChange = (e) = > {
const { name, value } = e.target;
console.log(name, value);
this.setState({
[name]:value
},() = >{
// The user has completed the input in the page
})
}
getFieldDecorator = (fieldName, option) = > {
// Set the field option configuration
this.options[fieldName] = option;
return (InputComp) = > {
return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); This. The state (fieldName) | | ', / / control value onChange: enclosing handlerChange, / / change event handling})}</div>}}render() {
return (
<Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} />
)
}
}
}
@MFormCreate
class MForm extends Component {
render() {
const { getFieldDecorator } = this.props;
return (
<div>{getFieldDecorator('username', {rules: [{required: true, message: "username is required"}]})(<input type='text' />)} {getFieldDecorator(' PWD ', {rules: [{required: true, message: "Password required"}]})(<input type='password' />)}<input type="submit" value='login' />
</div>); }}export default MForm;
Copy the code
Verification of form entry after completion
MFormCreate higher-order component
const MFormCreate = function (Comp) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};// Save the values of each field
this.options = {}; // Save the field option Settings
}
// Process the form entry event
handlerChange = (e) = > {
const { name, value } = e.target;
// console.log(name, value);
this.setState({
[name]: value
}, () = > {
// The user has entered the form in the page
this.validateField(name)
})
}
// Verify the form entry
validateField = (fieldName) = > {
const { rules } = this.options[fieldName];
const ret = rules.some(rule= > {
if (rule.required) {
// If the input field value is null
if (!this.state[fieldName]) {
this.setState({
[fieldName + 'Message']: rule.message
})
return true; // Verification failed, return true}}})// console.log(ret);
if(! ret) {this.setState({
[fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
}
getFieldDecorator = (fieldName, option) = > {
// Set the field option configuration
this.options[fieldName] = option;
return (InputComp) = > {
return <div>{/ *... * /} {/ * validation shows * /} {this. The state [fieldName + "Message"] && (<p style={{ color: 'red' }}>{this.state[fieldName + 'Message']}</p>)}</div>}}render() {
return (
<Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} />)}}}Copy the code
Click submit button to verify
const MFormCreate = function (Comp) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};// Save the values of each field
this.options = {}; // Save the field option Settings
}
// Process the form entry event
handlerChange = (e) = > {
const { name, value } = e.target;
// console.log(name, value);
this.setState({
[name]: value
}, () = > {
// The user has entered the form in the page
this.validateField(name)
})
}
// Verify the form entry
validateField = (fieldName) = > {
const { rules } = this.options[fieldName];
const ret = rules.some(rule= > {
if (rule.required) {
// If the input field value is null
if (!this.state[fieldName]) {
this.setState({
[fieldName + 'Message']: rule.message
})
return true; // Verification failed, return true}}})// console.log(ret);
if(! ret) {this.setState({
[fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
}
validate = (cb) = > {
const rets = Object.keys(this.options).map(fieldName= > this.validateField(fieldName))
// If all the values in the array are true, the verification succeeds
const ret = rets.every(v= >v===true);
cb(ret);
}
getFieldDecorator = (fieldName, option) = > {
// Set the field option configuration
this.options[fieldName] = option;
return (InputComp) = > {
return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); This. The state (fieldName) | | ', / / control value onChange: This handlerChange, / / change event handling})} {this. The state [fieldName + "Message"] && (<p style={{ color: 'red' }}>{this.state[fieldName + 'Message']}</p>)}</div>}}render() {
return (
<Comp {. this.props} name='Joe' getFieldDecorator={this.getFieldDecorator} validate={this.validate} />
)
}
}
}
@MFormCreate
class MForm extends Component {
constructor(props) {
super(props);
}
handlerSubmit = () = > {
// If isValid is true, the verification succeeds; if flase is flase, the verification fails
this.props.validate((isValid) = > {
console.log(isValid);
if(isValid){
alert('Verification successful');
}else{
alert('Verification failed'); }})}render() {
const { getFieldDecorator } = this.props;
return (
<div>{/ *... * /}<input type="submit" value='login' onClick={this.handlerSubmit} />
</div>); }}Copy the code
Finally, wrap the FormItem and Input components
import React, { Component } from 'react';
import { Icon } from 'antd'
// Wrap the user form, add data management capability and validation function
const MFormCreate = function (Comp) {
return class extends Component {
constructor(props) {
super(props);
this.state = {};// Save the values of each field
this.options = {}; // Save the field option Settings
}
// Process the form entry event
handlerChange = (e) = > {
const { name, value } = e.target;
// console.log(name, value);
this.setState({
[name]: value
}, () = > {
// The user has entered the form in the page
this.validateField(name)
})
}
// Verify the form entry
validateField = (fieldName) = > {
const { rules } = this.options[fieldName];
const ret = rules.some(rule= > {
if (rule.required) {
// If the input field value is null
if (!this.state[fieldName]) {
this.setState({
[fieldName + 'Message']: rule.message
})
return true; // Verification failed, return true}}})// console.log(ret);
if(! ret) {this.setState({
[fieldName + 'Message'] :' '})}return! ret;// Verify success returns false
}
validate = (cb) = > {
const rets = Object.keys(this.options).map(fieldName= > this.validateField(fieldName))
// If all the values in the array are true, the verification succeeds
const ret = rets.every(v= > v === true);
cb(ret);
}
getFieldDecorator = (fieldName, option) = > {
// Set the field option configuration
this.options[fieldName] = option;
return (InputComp) = > {
return <div>{react. cloneElement(InputComp, {name: fieldName, // control name: value); Enclosing the state (fieldName) | | ', / / control value onChange: enclosing handlerChange, / / change event handling an onFocus: enclosing handlerFocus})}</div>}}// Control gets the focus event
handlerFocus = (e) = > {
const field = e.target.name;
console.log(field);
this.setState({
[field + 'Focus'] :true})}// Determine whether the control is clicked
isFieldTouched = field= >!!!!!this.state[field + 'Focus']
// Get control error information
getFieldError = field= > this.state[field + "Message"];
render() {
return (
<Comp
{. this.props}
getFieldDecorator={this.getFieldDecorator}
validate={this.validate}
isFieldTouched={this.isFieldTouched}
getFieldError={this.getFieldError}
/>)}}}// Create the FormItem component
class FormItem extends Component {
render() {
return (
<div className='formItem'>
{this.props.children}
{
this.props.validateStatus === 'error' && (<p style={ { color: 'red'}} >{ this.props.help}</p>)}</div>); }}// Create the Input component
class Input extends Component {
render() {
return (
<div>{/* prefix icon */} {this.props. Prefix}<input {. this.props} / >
</div>
);
}
}
@MFormCreate
class MForm extends Component {
constructor(props) {
super(props);
}
handlerSubmit = () = > {
// If isValid is true, the verification succeeds; if flase is flase, the verification fails
this.props.validate((isValid) = > {
console.log(isValid);
if (isValid) {
alert('Verification successful');
} else {
alert('Verification failed'); }})}render() {
const { getFieldDecorator, isFieldTouched, getFieldError } = this.props;
const usernameError = isFieldTouched('username') && getFieldError('username');
const pwdError = isFieldTouched('pwd') && getFieldError('pwd');
return (
<div>
<FormItem validateStatus={usernameError ? 'error' :"'}help={usernameError| | '} >{getFieldDecorator('username', {rules: [{required: true, message: "username is required ",}]})(<Input type='text' prefix={<Icon type='user' />}} / >)</FormItem>
<FormItem validateStatus={pwdError ? 'error' :"'}help={pwdError| | '} >{getFieldDecorator(' PWD ', {rules: [{required: true, message: "Password is required"}]})(<Input type='password' prefix={<Icon type='lock' />}} / >)</FormItem>
<input type="submit" value='login' onClick={this.handlerSubmit} />
</div>); }}export default MForm;
Copy the code
conclusion
- The React component is a top-down extension, passing the ability to extend from top to bottom, and the Input component can call the passed value at the appropriate time.
- React components are developed according to the following principle: the logic control is promoted to the upper layer, and the lower-level components are as dumb as possible, and do not touch the business logic.