To undertake detailed

Componentized actual combat

We from the common form component design and implementation to componentize the actual combat explained ~

Antd form use

// Implement user name and password login and verification// FormPage.js

import React, {Component, useEffect } from 'react';
import {Form, Input, Button } from 'antd';
 const FormItem = Form.Item;  const nameRules = { required: true, message: 'Please enter name :'}; const passwordRules = { required, message: 'Please enter password:'}  export default class AntdFormpage extends Component {  formRef = React.createRef();   componentDidMount() {  this.formRef.current.setFieldsValue({ name: 'default'});  }   onReset = () => {  this.formRef.current.resetFields();  }  onFinish = val => {  console.log('onFinish', val)  }   onFinishFailed = val => {  console.log('onFinishedFailed', val)  }  render() {  return (  <div>  <h3>AntdFormPage</h3>  <Form  ref={this.formRef}  onFinish= {this.onFinish}  onFinishFailed = {this.onFinishedFailed}  onReset= {this.onReset}  >  <FormItem label="Name" name="name" rules={[nameRules]}>  <Input placeholder="name input placeholder"/>  </FormItem>  <FormItem label="Password" name="password" rules={[passwordRules]}>  <Input placeholder="password input placeholder" />  </FormItem>  <FormItem>  <Button type="primary" size="large" htmlType="subnit">Submit</Button>  </FormItem>  <FormItem>  <Button type="default" size="large" htmlType="reset">Reset</Button>  </FormItem>  </Form>  </div>  )  } } Copy the code

Function implementation: Note that useForm is implemented by React Hooks and can only be used with function components.

export default function AntdFormPage(props) {
  const [form] = Form.useForm();
  
  const onFinish = val => {
    console.log('onFinish', val);
 }  const onFinishFailed = val => {  console.log('onFinishFailed', val);  }  const onReset = () => {  form.resetFields();  }   useEffect(() => {  form.setFieldsValue({name: 'default'});  }, [])   return (  <Form  form={form}  onFinish={onFinish}  onFinishFailed={onFinishFailed}  onReset={onReset}  >  <FormItem label="Name" name="name" rules={[nameRules]}>  <Input placeholder="name input placeholder" />  </FormItem>  <FormItem label="Password" name="password" rules={[passworRules]}>  <Input placeholder="password input placeholder" />  </FormItem>  <FormItem>  <Button type="primary" size="large" htmlType="submit">Submit</Button>  </FormItem>  <FormItem>  <Button type="default" size="large" htmlType="reset">Reset</Button>  </FormItem>  </Form>  ) } Copy the code

Antd4 form component implementation

Install rC-field-form and yarn add RC-field-form at github. Use useForm, function only:

import React, {Component, useEffect} from 'react';
import Form, {Field} from '.. /components/my-rc-fieldd-form/';
import Input from '.. /components/Input';

const nameRules = { required: true, message: 'Please enter your name! '}
const passworRules = { required: true, message: 'Please enter your password! '}  export default function MyRCFieldForm(props) {  const [form] = Form.useForm();   const onFinish = val => {  console.log('onFinish', val);  }   const onFinishFailed = val => {  console.log('onFinishFailed', val);  }   useEffect(() => {  form.setFieldsValue({userName: 'default'});  }, [])   return (  <div>  <h3>MyFieldForm</h3>  <Form from={form}  onFinish={onFinish}  onFinishFailed={onFinishFailed}  >  <Field name="username" rules={[nameRules]}>  <Input placeholder="input UR username" />  <Field>  <Field>  <Input placeholder="input UR password" />  </Field>  <button>Submit</button>  </Form>  </div>  ) } Copy the code

The class implementation

export default class MyRCFieldForm extends Component {
  formRef = React.createRef();
  componentDidMount() {
    this.formRef.current.setFieldsValue({username: 'default'});
  }
  onFinish = val => {  console.log('onFinish', val);  }   onFinishFailed = val => {  console.log('onFinishFailed', val);  }   render() {  return (  <div>  <h3>MyRcFieldForm</h3>  <Form  ref={this.formRef}  onFinish={onFinish}  onFinishFailed={onFinishFailed}  >  <Filed name="username" rules={[nameRules]}>  <Input placeholder="username"/>  </Field>  <Field name="password" rules={[passworRules]}>  <Input placeholder="Password" />  </Field>  <button>Submit</button>   </Form>  </div>  )  } } Copy the code

To realize my – rc – field – form

The realization of the Form/Index

import React from 'react';
import _Form from './Form';
import Field from './Field';
import useForm from './useForm';

const Form = React.forwardRef(_Form); Form.field = Field; Form.useForm = useForm;  export { Field, useForm }; export default Form; Copy the code

To realize the Form

import React from 'react';
import useForm from './useForm';
import FieldContext from './FieldContext';

export default function Form({children, onFinish, onFinishFailed, form}, ref) {
 const [formInstance] = useForm(form)   React.useImperativeHandle(ref, () => formInstance);   formInstance.setCallback({  onFinish,  onFinishFailed,  })   return (  <Form  onSubmit={  event => {  event.preventDefault();  event.stopPropagation();  formInstance.submit();  }  }  >  <FieldContext.Provider value={formInstance}>  {children}  </FieldContext.Provider>  </Form>  ) } Copy the code

Implement FieldContext

import React from 'recat';

const warnFunc = () => {
  console.log('-------error--------')
}
 const FieldContext = React.createContext({  registerField: warnFunc,  setFieldsValue: warnFunc,  getFieldValue: warnFunc,  getFieldsValue: warnFunc,  submit: warnFunc })  export default FieldContext; Copy the code

Implement useForm

import React from 'react';
class FormStore {
  constructor() {
this.store = {}; // Store data, such as username,password  this.fieldEntities = [];
 // callback onFinish onFinishFailed  this.callbacks = [];  }  / / register registerField = entity => {   this.fieldEntities.push(entity);  return() = > {thie.fieldEntities = this.fieldEntities.filter(item => item! ==entity); delete this.store[entity.props.name];  };  };   setCallback = callback => {  this.callbacks = { . this.callbacks,. callback, };  };  / / get data getFieldValue = name => {  return this.store[name];  }   getFieldsValue = () => {  return this.store;  }  / Set data setFieldsValue = newStore => {  this.store = { . this.store,. newStore, }   this.fieldEntities.forEach(entity => {  const {name} = entity.props;   Object.keys(newStore).forEach(key => {  if(key === name) {  entity.onStoreChange();  }  })  })  };   validate = () => {  let err = [];  this.fieldEntities.forEach(entity => {  const {name, rules} = entity.props;  let value = this.getFieldValue(name);  let rule = rules && rules[0];  if(rule && rule.required && (value === undefined || value === ' ')) { / / error err.push({  [name]: rules.messagee,  value  })  }  });  return err;  };   submit = () => {  console.log('this.fieldEntities', this.fieldEntities);  let err = this.validate(); // If the verification succeeds, execute onFinish; if the verification fails, execute onFinishFailed const {onFinish, onFinishFailed} = this.callbacks;  if(err.length === 0){ // If successful, execute onFinish onFinish(this.getFieldsValue());  }else if(err.length > 0) { // Failed to execute onFinishFailed onFinishFailed(err);  }  };  getForm = () => {  return {  registerField: this.registerField,  setCallback: this.setCallback,  submit: this.submit,  getFieldValue: this.getFieldValue,  getFiledsValue: this.getFieldsValue,  setFieldsValue: this.setFieldsValue,  };  };  // Custom hook export default function useForm(form) {  const formRef = React.useRef();  if(! form.current) { if(form){  formRef.current = form;  }else { / / the new one const formStore = new FormStore();  formRef.current = formStore.getForm();  }  }  return [formRef.current];  } } Copy the code

Implement Field

import React, {Component} from 'react';
import FieldContext from './FieldContext';

export default class Field extends Component {
  static contextType = FieldContext;
  componentDidMount() {  const {registerField} = this.context;  this.cancelRegisterField = registerField(this);  }   componentWillUnmount() {  if(this.cancelRegisterField) {  this.cancelRegisterField();  }  }   onStoreChange = () => {  this.forceUpdate();  }   getControlled = () => {  const {name} = this.props;  const {getFieldValue, setFieldsValue} = this.context;   return { Value: getFieldValue(name), // Fetch data onChange: event => { / / data const newValue = event.target.value;  setFieldsValue({[name]: newValue});  };  };  }   render() {  console.log('field render');   const {children} = this.props;   const returnChildNode = React.cloneElement(children, this.getControllled());  return returnChildNode;  } } Copy the code

To realize my – rc – form

import React, {Component} from 'react';
import createForm from '.. /components/my-rc-form/';

import Input from '.. /components/Input';

const nameRules = {required: true, message: 'Please enter your name! '}; const passworRules = {required:true, message: 'Please enter your password! '};   @createForm class MyRCForm extends Component {  constructor(props){  super(props);  }   componentDidMount() {  this.props.form.setFieldsValue({username: 'default'});  }   submit = () => {  const {getFieldsValue, validateFields} = this.props.form;  validateFields((err, val) => {  if(err) {  console.log('err', err);  }else {  console.log('Verification successful', val);  }  })  }   render() {  console.log('props', this.props);  const {getFieldDecorator} = this.props.form;  return (  <div>  <h3>MyRCForm</h3>  {  getFieldDecorator('username', {rules: [nameRules]})(  <Input placeholder="username"/>  )  }  {  getFieldDecorator('password', {rules: [passworRules]})(  <Input placeholder="Password"/>  )  }  <button onClick={this.submit}>submit</button>  </div>  )  } }  export default MyRCForm; Copy the code

implementation

import React, {Component} from 'react';
export default function createForm(Cmp) {
  return class extends Component {
    constructor(props){
      super(props);
 this.state = {};  this.options = {};  }   handleChange = e => {  const {name, value} = e.target;  this.setState({[name]: value});  }   getFieldDecorator = (field, option) => InputCmp => {  this.options[field] = option;  return React.cloneElement(InputCmp, {  name: field,  value: this.state[field] || ' '. onChange: this.handleChange  })  }   setFieldsValue = newStore => {  this.setState(newStore);  };  getFieldsValue = () => {  return this.state;  };  validatefields = callback => {  let err = []; // Verify the validation rule this.options// Check the value this.state  for(let field in this.options) { // Check whether state[field] is undefined// undefined err. Push ({[field]:'err'})  if(this.state[field] === undefined) {  err.push({  [field]: 'err'  });  }  }  if(err.length ===0){ // The verification succeeds callback(null, this.state);  }else{  callback(err, this.state);  }  };  getForm = () => {  return {  form: {  getFieldDecorator: this.getFieldDecorator,  setFieldsValue: this.setFieldsValue,  getFieldsValue: this.getFieldsValue,  validateFields: this.validateFields  }  }  }  render() {  return<Cmp {... this.props} {... this.getForm()} />; }  }  } Copy the code

Design and implementation of popover class components

The popover content is declared at A, but displayed at B. React’s equivalent popover content appears to be rendered into a component, but actually changes the DOM structure of a different part of the page. This doesn’t make sense. However, the task can still be accomplished by creating component instances and setting mount targets using specific apis provided by the framework.

The common usage is as follows: Dialog is declared by the current component, but is displayed in a separate div within the bodyimport React, {Component} from 'react';
import Dialog from '.. /components/Dialog';

export default class DialogPage extends Component {
 constructor(props) {  super(props);  this.state = {  showDialog: false  };  }   render() {  const {showDialog} = this.state;  return (  <div>  <h3>DialogPage</h3>  <button onClick={()=> this.setState({ showDialog: ! showDialog})} > toogle  </button>  {showDialog && <Dialog />}  </div>  )  } } Copy the code

Implementation :Portal

After React V16, Portal provides the content transfer function. Dialog component

// Dialog.js
import React, {Component} from 'react';
import { createPortal } from 'react-dom';

export default class Dialog extends Component {
 constructor(props) {  super(props);  const doc = window.document;  this.node = doc.createElement('div');  doc.body.appendChild(this.node);  }  componentWillUnmount() { window.document.body.removeChild(this.node);  }  render() {  const {hideDialog} = this.props;  return createPortal(  <div className="dialog">  {this.props.children}  {  typeof hideDialog === 'function' && ( <button onClick={hideDialog}> Close the popover </button> )  }  </div>,  this.node,   )  } }  .dialog {  position: absolute;  top: 0;  right: 0;  bottom: 0;  left: 0;  line-height: 30px;  width: 400px;  height: 300px;  transform: translate(50%,50%);  border: solid 1px gray;  text-align: center; } Copy the code

To sum up:

All Dialog does is draw the object in another corner of the DOM tree by calling createPortal.

The last

Happy National Day!! Spend more time with your family and be happy!