?? In order to separate the business logic code and reuse the related business logic within the component, several schemes such as Mixin, hoc, and render props are released in sequence for code reuse in the react iteration. In addition, for function components, the hooks concept is proposed in react v16.7.0-Alpha. In stateless function components, an independent state space is introduced, that is, in function components, you can also introduce the state and life cycle of Class components to enrich function components. In addition, hooks ensures the reusability and independence of logical code.
?? Starting from the reuse solution for Class components, this article describes the evolution from Mixin, HOC to render props, and finally introduces hooks in react v16.7.0-alpha and custom hooks.
- Mixin
- Hoc
- Render props
- React hooks introduction and how to customize a hooks
In my blog: https://github.com/forthealll...
Welcome to star and fork ~
I. Mixin
Mixin is the first solution to reuse the business logic code in Class components. First, we will introduce how to adapt to Mixin. The following is an example of Mixin:
const someMixins={ printColor(){ console.log(this.state.color); } setColor(newColor){ this.setState({color:newColor}) } componentDidMount(){ .. }}
The following is a component using Mixin:
Class Apple extends react. component {// only for demonstration. mixins generally use react. createclass is created, and es6 does not write mixins as follows: [somemixins] Constructor (props) {super (props); this. state = {color: 'red'} This. printcolor = This. printcolor. BIND (this);} render () {return & lt; Div classname = "M-box" onclick = {This. printcolor} & gt; this is an apple & lt;/Div & gt ;}}
Introduce the public service logic into Mixin:
mixins:[someMixins]
From the above example, we will summarize the following Disadvantages of Mixin:
- Mixin can exist in multiple forms and is in the form of an array, and functions in Mixin can call the state in the setstate method component, therefore, if the same state is modified in multiple Mixin modules, the update source of the State cannot be determined.
- Es6 classes supports the inherited mode, but does not support mixins.
- Mixin overwrites. For example, if two Mixin modules have functions with the same lifecycle function or function name, the same function overwrites occur.
Mixin has been abolished. For details about the defects, refer to mixins considered harmful.
Ii. hoc
?? To solve Mixin defects, the second solution is high order component (HOC ).
1. Examples of several hoc forms
?? A simple understanding of hoc is that the component factory accepts the original component as a parameter. After adding functions and services, the new component is returned. The following describes several examples of hoc parameters.
(1) The parameter is only for the original component.
const redApple = withFruit(Apple);
(2) parameters are the original component and an object.
const redApple = withFruit(Apple,{color:'red',weight:'200g'});
However, this situation is rarely used. If only attributes are transmitted in the object, in fact, the props of the component can be used to realize value transfer. The main purpose of hoc is to separate services, we usually use props to specify the UI display and attributes and States of some components for convenience.
(3) parameters are the original component and a function.
const redApp=withFruit(App,()=>{console.log('I am a fruit')})
(4) kerihua
The most common is to use only one original component as the parameter, but the business logic is encapsulated in the outer layer, such as the conect function of react-Redux:
class Admin extends React.Component{}const mapStateToProps=(state)=>{ return { };}const mapDispatchToProps=(dispatch)=>{ return { }}const connect(mapStateToProps,mapDispatchToProps)(Admin)
2. disadvantages of hoc
Hoc solves some Mixin defects, but hoc has some disadvantages:
(1) difficult to trace and attribute coverage problems exist.
?? If the original component A goes through factory function 1, factory function 2, factory function 3 .... Construct and finally generate component B. We know that component B has many props different from component A, but we only use component B and cannot know which component comes from which factory function. At the same time, if two factory functions modify a property of the same name of component A at the same time, there will be an attribute overwrite problem, which will invalidate the Modification result of the previous factory function.
(2) hoc is built statically.
?? The so-called static build, that is to say, generates a new component and does not immediately render it. The Hoc component factory builds a component statically, which is similar to re-declaring a component. That is to say, the periodic function declared in the Hoc factory function will be executed only when the new component is rendered.
(3) useless empty components will be generated. 3. Render prop
?? Render props is also a solution to remove reusable logic code and improve component reusability. In a reusable component, a property named "render" (the attribute name may not be a render, as long as the value is a function) is used as a function, this function accepts an object and returns a child component. The object in this function parameter is passed as a props to the newly generated component.
?? This method is different from directly passing the state in the parent component to the child component in the parent component. The render props does not need to write the child component, you can dynamically decide which child component the parent component needs to render.
Or, to sum up:
Render props is a function that is assigned to the parent component as an attribute so that the parent component can render the child component according to this attribute.
(1) standard parent-child component communication method
?? First, let's take a look at the commonly used parent and child components that are commonly used in Class components. The parent component passes its state to the child component through props.
class Son extends React.Component{ render(){ const {feature} = this.props; return <div> <span>My hair is {feature.hair}</span> <span>My nose is {feature.nose}</span> </div> }}class FatherToSon extends React.Component{ constructor(){ this.state = { hair:'black', nose:'high' } } render(){ return <Son feature = {this.state}> }}
?? We defined the parent component fathertoson, which has its own State and passed its state to the child component through props.
?? This is a common way to pass values between parent and child components using props. This value can be a variable, an object, or a method, however, only specific sub-components can be used at a time. If a daughter component also wants to reuse the methods or states in the parent component, you must create a new component:
class FatherToDaughter extends React.Component{ constructor(){ this.state = { hair:'black', nose:'high' } } render(){ return <Daughter feature = {this.state}> }}
From the above example, we can see that the communication method of the Parent and Child components in the standard mode can pass the status and functions of the parent component, but it cannot be reused.
(2) Rendering of render props
Based on the features of render props:
Render props is a function that is assigned to the parent component as an attribute so that the parent component can render the child component according to this attribute.
Implement the example in (1.
class FatherChild extends React.Component{ constructor(){ this.state = { hair:'black', nose:'high' } } render(){ <React.Fragment> {this.props.render} </React.Fragment> }}
In this case, if the child component needs to reuse the attributes or functions of the parent component, it can be used directly. For example, the Child component son can now directly call:
<FatherChild render={(obj)=>(<Son feature={obj}>)} />
If the child component daughter needs to reuse the method of the parent component, you can directly call:
<FatherChild render={(obj)=>(<Daughter feature={obj}>)} />
?? From this example, we can see that through render props, we have implemented a component factory that can reuse the business logic code. Compared with hoc, render props has the following advantages.
- Don't worry about props naming
- It can be traced. The props of sub-components must come from the direct parent component.
- Is built dynamically.
Render props also has one disadvantage:
It is impossible to use SCU to optimize rendering performance.
4. React hooks introduction and how to customize a hooks
?? The hooks concept was proposed in react conf 2018 and will be introduced in future versions. Hooks follows the concept of functional programming, the main purpose is to introduce the status and lifecycle of Class components in function components, and these statuses and lifecycle functions can also be removed to achieve reuse while reducing the complexity and ease of use of function components.
?? Hooks-related definitions are still in Beta. You can experience them in react v16.7.0-Alpha. to render the function components defined by hooks, the react-dom version must be v16.7.0-Alpha, to introduce hooks, you must first install:
npm i -s [email protected]npm i -s [email protected]
?? Hooks consists of three parts: State hooks, effect hooks, and custom hooks.
(1) State hooks
?? Like a Class component, the state here is the meaning of the State. It is introduced into the function component, and the method for updating the state in the class component is setstate, there are also corresponding update Methods in State hooks.
Function examplewithmanystates () {// Method for declaring various states and updating corresponding states const [age, setage] = usestate (42); const [fruit, setfruit] = usestate ('bana'); const [Todos, settodos] = usestate ([{text: 'learn hooks'}]); //...}
?? The preceding three State hooks are declared, and the corresponding method is usestate. This method creates an input initial value and a State. Returns a variable that identifies the state and the method for updating the state.
?? From the above example, a function component can create multiple States through usestate. In addition, the definition of State hooks must be at the highest level of function components and cannot be used in nested or loop statements.
Function examplewithmanystates () {// Method for declaring various states and updating corresponding states if (math. random () & gt; 1) {const [age, setage] = usestate (42); const [Todos, settodos] = usestate ([{text: 'Learn hooks'}]);} else {const [fruit, setfruit] = usestate ('bana'); const [Todos, settodos] = usestate ([{text: 'Learn hooks'}]);} //...}
?? The preceding method is not allowed because a function component can have multiple state hooks and usestate returns an array. Each element of the array has no identification information, the order in which usestate is called is used to determine which State corresponds to which variable. Therefore, usestate must be used in the outermost layer of the function component, in addition, the efficiency hooks function useeffect described later must be in the outermost layer of the function component and will be explained in detail later.
(2) effect hooks
?? The State Hooks is used to define the component state, and the life cycle is also introduced through effect hooks. effect hooks introduces the life cycle in a very simplified way through a useeffect method.
Let's look at an updated example:
import { useState, useEffect } from 'react';function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> );}
The above is an example of implementing the life cycle of components through useeffect. useeffect integrates componentdidmount and componentdidupdate, that is, the useeffect function is executed once during componentdidmount and componentdidupdate, in addition, to implement the Life Cycle Function componentwillunmount, if the useeffect function returns a function, it is defined as a function executed within the cycle of componentwillunmount.
Useeffect () = & gt; {// function body of the componentdidmount and componentdidupdate cycles return () = & gt ;{// function body of the componentwillunmount cycle }});
If multiple usestates and useeffect exist, they must be written in order. After defining a usestate, A useeffect function is used immediately.
useState('Mary') useEffect(persistForm) useState('Poppins') useEffect(updateTitle)
Therefore, the useeffect function must be at the highest level of the function component.
(3) supplement of effect hooks
We know that useeffect actually contains componentdidmount and componentdidupdate. If our method is to be executed only when componentdidmount is used, an empty array must be passed as the second parameter.
Useeffect () = & gt; {// executed only when componentdidmount}, []);
The above method will only be executed when componentdidmount, that is, the function component is rendered for the first time. After that, the status will be updated in a timely manner and will not be executed.
In addition, the following operations can be performed to reduce unnecessary state updates and rendering:
Useeffect () = & gt; {// executed only when componentdidmount}, [statename]);
In the preceding example, the useeffect function is executed only when the statename value changes.
(4) custom hooks
The usestate and useeffect states and life cycle functions can be detached to form a new function, which is a custom encapsulated hooks.
This is my hooks ---> dom-location,
This can be introduced as follows:
npm i -s dom-location
And can be used in function components. This custom Hooks is also very simple, that is, it encapsulates the state and lifecycle functions.
import { useState, useEffect } from 'react'const useDomLocation = (element) => { let [elementlocation,setElementlocation] = useState(getlocation(element)); useEffect(()=>{ element.addEventListener('resize',handleResize); return ()=>{ element.removeEventListener('resize', handleResize); } },[]); function handleResize(){ setElementlocation(getlocation(element)); } function getlocation(E){ let rect = E.getBoundingClientRect() let top = document.documentElement.clientTop let left= document.documentElement.clientLeft return{ top : rect.top - top, bottom : rect.bottom - top, left : rect.left - left, right : rect.right - left }; } return elementlocation}
Then directly use the following in the function:
import useDomLocation from 'dom-location';function App() { .... let obj = useDomLocation(element); }
Original article address: 1190000016876476
From Mixin to hooks, let's talk about the coming hooks in react16.7.0-Alpha.