React from entry to master (1704B)

React from entry to master (1704B)

table of Contents

1. Introduction to React

2. the background and principles of React

3. JSX introduction

4. React components

5. scaffolding

6. shortcuts

7. state and props

8. components

9. todo list exercises

10. Life cycle

Eleven, routing

12. Use PropTypes for type checking

Thirteen, refs and DOM

14. ReactDOM

15. Mock data

16. antd

Seventeen, Context

18. Event system

19. Redux

Twenty, redux-thunk

Twenty-one, flex three-stage

22. Xiaomi Book City

Twenty-three, Dangdang

Twenty-four, carousel diagram

Twenty-five, login and component nesting

Twenty-six, cat's eye

Twenty-seven, shopping cart

other


 

 

 

 

 

 

1. Introduction to React

React originated from Facebook 's internal project. Because the company was not satisfied with all JavaScript MVC frameworks on the market, it decided to write a set of its own to build an Instagram website ( www.instagram.com/ ). After making it, I found that this set of things is very useful, and it was open sourced in May 2013 ( github.com/facebook/re... ). Because React's design philosophy is extremely unique, it is a revolutionary innovation, with outstanding performance, but the code logic is very simple. Therefore, more and more people begin to pay attention to and use it, thinking that it may be the mainstream tool for Web development in the future.

Official website: react.docschina.org/

English official website: reactjs.org/

Recommended books: blog.csdn.net/xutongbao/a...

Novice tutorial: www.runoob.com/react/react...

Chinese community: react-china.org/

Comparison of NPM downloads: npmcharts.com/compare/rea...

instagram:

 

react github:

2. the background and principles of React

In Web development, we always need to reflect the changed data to the UI in real time, and then we need to manipulate the DOM. Complex or frequent DOM operations are usually the cause of performance bottlenecks (how to perform high-performance complex DOM operations is usually an important indicator of the skills of a front-end developer).

React introduces a virtual DOM (Virtual DOM) mechanism for this purpose: A set of DOM API is implemented with Javascript on the browser side.

Virtual DOM is essentially a cache between JS and DOM. It can be analogous to CPU and hard disk. Since the hard disk is so slow, we will add a cache between them: since the DOM is so slow, we will add a cache between their JS and DOM. The CPU (JS) only manipulates the memory (Virtual DOM), and then writes the changes to the hard disk (DOM) at the end.

React implements the DOM diff algorithm on Virtual DOM. When the data is updated, the corresponding update strategy will be calculated through the diff algorithm, and try to only update the actual browser DOM on the changed part, instead of directly re-rendering the entire DOM tree. , So as to achieve the purpose of improving performance.

You give me a piece of data, I generate a brand new Virtual DOM based on this data, and then diff with the Virtual DOM I generated last time to get a patch, and then hit the patch to the browser's DOM.

Don t tell me step by step how to do this, what to do first and then chop stuffing, NO, tell me whether you want pancakes or mooncakes, I will find a way to do it, don t interfere with me.

Even if I generate virtual dom, even if I ran diff, the time saved by simplifying those DOM operations based on patch is still considerable. So overall, it's still relatively fast.

Use JavaScript object structure to represent the structure of the DOM tree; then use this tree to build a real DOM tree, insert it into the document, and rebuild a new object tree when the state changes. Then compare the new tree with the old tree, record the difference between the two trees, apply the difference to the real DOM tree, and the view is updated.

3. JSX introduction

HTML language is written directly in JavaScript language, which is the syntax of JSX (JavaScript and XML). JSX is a grammatical extension of JavaScript, which allows the mixing of HTML and JavaScript. JSX is a set of syntactic sugar developed by facebook for the React framework . Syntactic sugar is also called sugar-coated syntax. It refers to a certain syntax added to the computer language. This syntax has no effect on the function of the language, but it is more convenient for programmers to use. The main purpose is to increase the readability of the program, thereby reducing the chance of program code errors. JSX is a kind of syntactic sugar of JS, similar to CoffeeScript and TypeScript, they will eventually be parsed into JS before they can be understood and executed by the browser. If the browser is not parsed, there is no way to recognize them. There are deficiencies.

const element = < h1 > Hello, world! </h1 > ; Copy code

The above seemingly strange tag syntax is neither a string nor HTML. It is called JSX. A great convenience brought by JSX is that we can write DOM-like structures directly in JS , rather than using native JS. It is much more convenient and simple to concatenate strings and then use regular replacement to render the template. It is recommended to use JSX in React to describe the user interface. JSX is used to declare elements in React. At first glance, it may look like a template language, but in fact it is completely implemented inside JavaScript.

You can use JavaScript expressions in JSX arbitrarily, and the expressions in JSX should be enclosed in braces. Examples are as follows:

const names = [ 'Jack' , 'Tom' , 'Alice' ]; const element = ( < div > {names.map(function (name) {return < div > Hello, {name}! </div > }) } </div > ); Copy code

 

When writing JSX, line breaks and indentation are usually added, which can enhance the readability of the code. At the same time, it is recommended to add a parenthesis to the outside of the JSX code , so as to prevent the bug of automatic insertion of semicolons.

Above we declared an array of names, and then traversed the array of names and added Hello in front to generate an array of elements. JSX allows to insert JavaScript variables directly in the template. If this variable is an array, all members of this array will be expanded. JSX itself is actually an expression. After compilation, JSX will actually be converted into ordinary JavaScript objects. code show as below:

<!DOCTYPE html> < html > < head > < meta charset = "UTF-8"/> < title > Hello World </title > < script src = "https://unpkg.com/react@16/umd/react.development.js" > </script > < script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js" > </script > < script src = " https://unpkg.com/babel-standalone@6.15.0/babel.min.js"> </script > </head > < body > < div id = "root" > </div > < script type = "text/babel" > const names = [ 'Jack' , 'Tom' , 'Alice' ] ; const element = names.map( function ( name, index ) { return < div key = {index} > Hello, {name}!</div > }); ReactDOM.render( element, document .getElementById( 'root' ) ) </script > </body > </html > Copy code

JSX attributes:

You can use quotation marks to define attributes with string values:

const element = < div tabIndex = "0" > </div > ; Copy code

You can also use curly braces to define attributes whose values are JavaScript expressions:

const element = < img src = (user.avatarUrl) > </img > ; Copy code

Remember not to put quotation marks around when using JavaScript expressions wrapped in curly braces. JSX will recognize the content in the quotation marks as a string instead of an expression

4. React components

As the core content of React, components are an important part of View. Each View page is composed of one or more components. It can be said that components are the cornerstone of React applications. In the composition of React components, according to the state, it can be divided into stateful components and stateless components .
The so-called stateless component is a component that has no state control and only serves as a purely static display. The stateless component is the most basic form of component, which is composed of the attribute props and the rendering function render. Since it does not involve status updates, this type of component has the strongest reusability.
Stateful components add internal state management of components on the basis of stateless components. Stateful components usually have a lifecycle to trigger state updates at different times. Stateful components are widely used in business logic development. in.

Next we encapsulate a component that outputs "Hello World!" , the component name is HelloMessage: 

function HelloMessage ( props ) { return < h1 > Hello World! </h1 > ; } const element = < HelloMessage/> ; ReactDOM.render( element, document .getElementById( 'example' ) ); Copy code

Example analysis:

1. We can use a function to define a component:

function HelloMessage ( props ) { return < h1 > Hello World! </h1 > ; } Copy code

You can also use ES6 class to define a component:

class HelloMessage extends React . Component { render () { return < h1 > Hello World! </h1 > ; } } Copy code

2. const element = <HelloMessage/> is a user-defined component.

Note that native HTML element names start with lowercase letters, while custom React class names start with uppercase letters . For example, HelloMessage cannot be written as helloMessage. In addition, note that the component class can only contain one top-level label , otherwise an error will be reported.

If we need to pass parameters to the component, we can use this.props object, examples are as follows:

function HelloMessage ( props ) { return < h1 > Hello {props.name}! </h1 > ; } const element = < HelloMessage name = "Runoob"/> ; ReactDOM.render( element, document .getElementById( 'example' ) ); Copy code

Note that when adding attributes, the class attribute needs to be written as className and the for attribute needs to be written as htmlFor , because class and for are reserved words of JavaScript.

Composite components:

We can synthesize a component by creating multiple components, that is, to separate the different functional points of the component.

In the following example, we have implemented a component that outputs the website name and URL:

function Name ( props ) { return < h1 > Website name: {props.name} </ h1 > ; } function Url ( props ) { return < h1 > Website address: {props.url} </h1 > ; } function Nickname ( props ) { return < h1 > Website nickname: {props.nickname} </h1 > ; } function App () { return ( < div > < Name name = "Rookie Tutorial"/> < Url url = "http://www.runoob.com"/> < Nickname nickname = "Runoob"/> </div > ); } ReactDOM.render( < App/> , document .getElementById( 'example' ) ); Copy code

5. scaffolding

npx create-react-app my-app cd my-app npm start Copy code

Reference link: facebook.github.io/create-reac...

When developing a react application, no one should use the traditional method to import the react source file (js), and then edit it in html.

Everyone uses webpack + es6 to combine react to develop front-end applications.

At this time, we can manually use npm to install various plug-ins to build our own environment from start to finish.

Although the process of building it by yourself is also a good learning process, sometimes it is inevitable to encounter various problems, especially for beginners, and every time you develop a new application, you have to build it from scratch, which is too cumbersome.

Therefore, some people developed scaffolding based on their own experience and best practices to avoid duplication of wheels and wasteful work during the development process, thereby saving development time.

create-react-app: github.com/facebook/cr...

6. shortcuts

VSC install ES7 React/Redux/GraphQL/React-Native snippets

rcc:

Import React, the Component {} from 'REACT' export default class App extends Component { render () { return ( < div > </div > ) } } Copy code

rcreudx:

Import React, the Component {} from 'REACT' Import PropTypes from 'prop-types' Import {Connect} from 'REACT-Redux' export class App extends Component { static propTypes = { prop : PropTypes } render () { return ( < div > </div > ) } } const mapStateToProps = ( state ) => ({ }) const mapDispatchToProps = { } Export default Connect (mapStateToProps, mapDispatchToProps) (the App) copying the code

imrc:

Import React, the Component {} from 'REACT' duplicated code

7. state and props

1. The difference

props is a component of the interface outside , state component is the internal interface . Other components can be referenced within components, and the references between components form a tree structure (component tree). If the lower-level components need to use the data or methods of the upper-level components, the upper-level components can be passed through the props properties of the lower-level components, so props It is the external interface of the component. In addition to using the data passed by the upper-level component, the component itself may also need to maintain and manage data. This is the internal interface state of the component. According to the external interface props and internal interface state, the component calculates the UI of the corresponding interface.

The main difference:

  •     State is variable and is a set of states used to reflect changes in the component UI;
  •     Props is read-only for the components that use it. If you want to modify Props, you can only modify it through the parent component of the component. In the scenario where the state of the component moves up, the parent component passes the state required by the child component to the child component through the Props of the child component.

The core idea of React is componentization , and the most important concept in components is State. State is the UI data model of a component and is the data basis for component rendering.

State (state) is similar to properties (props), both are some data collections required by a component, but state is private, and state can be considered as a "private property (or local property)" of the component.

2. Use setState to modify State

Modify the state directly, the component will not trigger render() again

//error this .state.comment = 'Hello' ; copy the code

The correct way to modify is to use setState()

//correct the this .setState ({ Comment : 'the Hello' }); duplicated code

3. The update of State is asynchronous

 

To sum up:
this.props and this.state may be updated asynchronously , you cannot rely on their values to calculate the next state (state)

  • After calling setState, setState will put the state to be modified into a queue (so the state of the component will not change immediately);
  • Afterwards, React will optimize the real execution timing to optimize performance. Therefore, during the optimization process, multiple setState state modifications may be merged into one state modification, so state updates may be asynchronous.
  • So don't rely on the current State, calculate the next State. When the state modification is actually performed, the dependent this.state is not guaranteed to be the latest State, because React will merge multiple State modifications into one. At this time, this.state will still be the State before these few State modifications. Another thing to note is that you cannot rely on the current Props to calculate the next state, because Props are generally obtained from the State of the parent component, and it is still impossible to determine the value when the component state is updated.

8. components

The parent and child components pass by value, and the child component calls the method of the parent component

Control.js:

import React, {Component} from'react' class Control extends Component { constructor(props) { super(props) } handleAdd() { this.props.onAdd() } render() { return ( < div > < button onClick = {this.handleAdd.bind(this)} > Add </button > </div > ) } } export default Control Copy code

Index.js:

Import React, the Component {} from 'REACT' Import Control from '../components/Control.js' class Index extends Component { constructor ( props ) { super (props) this .state = { count : 0 } } handleAdd () { let {count} = this .state count = count + 1 this .setState({ count }) } render () { let {count} = this .state return ( < div > < div > {count} </div > < div > < Control onAdd = {this.handleAdd.bind(this)}/ > </div > </div > ) } } Export default Index copy the code

9. todo list exercises

www.todolist.cn/

The key of an element is preferably a unique string that the element has in the list. Usually, we use the id from the data as the key of the element:

const todoItems = todos.map( ( todo ) => < li key = {todo.id} > {todo.text} </li > ); Copy code

github address:

github.com/baweireact/...

 

Animated version of todolist:

chenglou.github.io/react-motio...

 

10. Life cycle

common:

Including the less commonly used:

Life cycle before React v16.0: ****

Reference link: projects.wojtekmaj.pl/react-lifec...

Text description: zh-hans.reactjs.org/docs/react-...

Instance period: componentWillMount render componentDidMount

Lifetime: componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate

Destruction period: componentWillUnmount

The latest life cycle:

getDerivedStateFromProps:

Parent component:

Import React, the Component {} from 'REACT' Import the Count from '../components/Count.js' class Index extends Component { constructor ( props ) { super (props); this .state = { count : 0 } } handleAdd () { let {count} = this .state count = count + 1 this .setState({ count }) } componentDidMount () { } render () { let {count} = this .state return ( < div > < Count count = {count} > </Count > < button onClick = {this.handleAdd.bind(this)} > Add </button > </div > ) } } Export default Index copy the code

Subassembly:

Import React, the Component {} from 'REACT' class Count extends Component { constructor ( props ) { super (props) this .state = { count : 0 } } static getDerivedStateFromProps ( props, state ) { return { count : props.count } } render () { let {count} = this .state return ( < div > {count} </div > ) } } Export default the Count Copy the code

getSnapshotBeforeUpdate

Parent component:

Import React, the Component {} from 'REACT' Import ScrollingList from '../components/ScrollingList.js' class Index extends Component { constructor ( props ) { super (props); this .state = { list :[] } } handleAdd () { let {list} = this .state list.unshift({ id : ( new Date ()).getTime(), text : 'xu' + ( new Date ()).getTime(), }) this .setState({ list }) } render () { let { list } = this .state return ( < div > < button onClick = {this.handleAdd.bind(this)} > Add </button > < ScrollingList list = {list} > </ScrollingList > </div > ); } } Export default Index copy the code

Subassembly:

Import React, the Component {} from 'REACT' Import './index.css' class ScrollingList extends Component { constructor ( props ) { super (props); this .listRef = React.createRef(); } getSnapshotBeforeUpdate ( prevProps, prevState ) { //Do we add new items to the list? //Capture the scroll position so that we can adjust the scroll position later. if (prevProps.list.length < this .props.list.length || true ) { const list = this .listRef.current; return list.scrollHeight-list.scrollTop; } return null ; } componentDidUpdate ( prevProps, prevState, snapshot ) { //If our snapshot has a value, it means that we have just added new items. //Adjust the scroll position so that these new items will not push the old items out of the view. //(The snapshot here is the return value of getSnapshotBeforeUpdate) if (snapshot !== null ) { const list = this .listRef.current; list.scrollTop = list.scrollHeight-snapshot; //list.scrollTop = snapshot } } render () { let { list } = this .props return ( < div > < ul className = "m-list-wrap" ref = {this.listRef} > { list.map(item => ( < li key = {item.id} > {item.text} </li > )) } </ul > </div > ); } } Export default ScrollingList copy the code

Eleven, routing

Reference link: reacttraining.com/react-route...

Commonly used apis are:

BrowserRouter: package root component

Switch: If there is a <Switch> tag, the <Route> will only match the first one when the path is the same. This can avoid repeated matching

Route: routing

Link: Link

withRouter: Package the component, the props of the package will add three attributes: match, location, history

1) Jump route through js: this.props.history.push('/tasklist')

2) Obtain dynamic routing parameters

    let {match} = this.props
if (match.params.new ==='new') {
}

3) Get the path name: <div>{this.props.location.pathname}</div>

 Switch was added first, and exact was added second. Joining Switch means that only one component is displayed. Add exact means exact match/

In a broad sense, nested routing can be divided into two situations: one is that each routed component has common content, and then the common content is separated into one component, and the changed content is also a component. This kind of component combination is nested to form a new component. The other is a sub-route, and there are routes inside the components that are routed to.

For shared content, the typical representative is the sidebar of the webpage. Assuming that the sidebar is on the left, when we click on the button, the content on the right will change, but no matter how the content on the right changes, the sidebar on the left The bar always exists.

Both BrowserRouter and HashRouter can implement the front-end routing function. The difference is that the former is based on the pathname segment of the URL , and the latter is based on the hash segment.

The former: http://127.0.0.1:3000/article/num1

The latter: http://127.0.0.1:3000/#/article/num1 (not necessarily so, but # is indispensable)

The direct problem caused by this difference is that when the page is refreshed in the second or multi-level routing state, the former will send the current route to the server (because it is the pathname), while the latter will not (because it is the hash segment).

Multi-level routing:

Use react-router-dom router.js:

Import React, the Component {} from 'REACT' Import {Switch, the Route, the Redirect} from 'REACT-Router-DOM' Import the Login from '../pages/Login.js' Import Header from ' ../components/Header. js' import Sidebar from '../components/Sidebar.js' import CityNav from '../components/CityNav.js' import CityNavForShanDong from '../components/CityNavForShanDong.js' import DistrictNav from '../components/DistrictNav.js' import ShanXi from '../pages/province/ShanXi.js' Import Tangshan from ' ../pages/province/city/TangShan.js' Import QINHUANGDAO from '../pages/province/city/QinHuangDao.js' Import Jinan from ' ../pages/province/city/JiNan.js' import QingDao from '../pages/province/city/QingDao.js' import YanTai from '../pages/province/city/YanTai.js' import ChangAn from '../pages/province/city/district/ChangAn.js' import QiaoXi from '../pages/province/city/district/QiaoXi.js' import XinHuafrom '../pages/province/city/district/XinHua.js' import './index.css' class Router extends Component { render () { return ( < div > < Switch > < Route path = '/' exact = {true} component = {Login} > </Route > < Route path = '/index' > < Route > < Header > </Header > < Sidebar > </Sidebar > </Route > <Switch > <Route path = "/index/hebei" > < Route > < CityNav > </CityNav > </Route > < Switch > < Route path = "/index/hebei/shijiazhuang" > < Route > < DistrictNav > </DistrictNav > </Route > < Switch > < Route path = "/index/hebei/shijiazhuang/changan" component = {ChangAn}> </Route > < Route path = "/index/hebei/shijiazhuang/qiaoxi" component = {QiaoXi} > </Route > < Route path = "/index/hebei/shijiazhuang/ xinhua " component = {XinHua} > </Route > </Switch > </Route > < Route path = "/index/hebei/tangshan" component = {TangShan} > </Route > <Route path = "/index/hebei/qinhuangdao" component = {QinHuangDao} > </Route > </Switch > </Route > < Route path = "/index/shandong" > < Route > < CityNavForShanDong > </CityNavForShanDong > </Route > < Route path = "/index/shandong/jinan" component = {JiNan} > </Route > < Route path ="/index/shandong/qingdao" component = {QingDao} > div</Route > < Route path = "/index/shandong/yantai" component = {YanTai} > </Route > </Route > < Route path = "/index/shanxi" component = {ShanXi} > </Route > </Switch > </Route > </Switch > </> ) } } Export default Router copy the code

github source code (using react-router-dom):

github.com/baweireact/...

 

 

Use react-router-config routerConfig.js:

Import React from 'REACT' ; Import {} renderRoutes from "Router-config-REACT" ; Import the Login from '../pages/Login.js' Import Header from ' ../components/Header.js' Import Sidebar from ' ../components/Sidebar.js' import CityNav from '../components/CityNav.js' import CityNavForShanDong from '../components/CityNavForShanDong.js' import DistrictNav from '../components/ DistrictNav.js 'import ShanXifrom '../pages/province/ShanXi.js' Import Tangshan from '../pages/province/city/TangShan.js' Import QINHUANGDAO from '../pages/province/city/QinHuangDao.js' Import Jinan from '../pages/province/city/JiNan.js' import QingDao from '../pages/province/city/QingDao.js' import YanTai from '../pages/province/city/YanTai.js' import ChangAn from '../pages/province/city/district/ChangAn.js' import QiaoXi from '../pages/province/city/district/QiaoXi.js' importXinHua from '../pages/province/city/district/XinHua.js' const Root = ( {route} ) => ( < div > {renderRoutes(route.routes)} </div > ); const Index = ( {route} ) => ( < div > < Header > </Header > < Sidebar > </Sidebar > {renderRoutes(route.routes)} </div > ); const HeBei = ( {route} ) => ( < div > < CityNav > </CityNav > {renderRoutes(route.routes)} </div > ); const ShiJiaZhuang = ( {route} ) => ( < div > < DistrictNav > </DistrictNav > {renderRoutes(route.routes)} </div > ); const ShanDong = ( {route} ) => ( < div > < CityNavForShanDong > </CityNavForShanDong > {renderRoutes(route.routes)} </div > ); const routes = [ { component : Root, routes : [ { path : "/" , exact : true , component : Login }, { path : "/index" , component : Index, routes : [ { path : "/index/hebei" , component : HeBei, routes : [ { path : "/index/hebei/shijiazhuang" , component : ShiJiaZhuang, routes : [ { path : '/index/hebei/shijiazhuang/changan' , component : ChangAn, }, { path : '/index/hebei/shijiazhuang/qiaoxi' , component : QiaoXi, }, { path : '/index/hebei/shijiazhuang/ xinhua ' , component : XinHua, } ] }, { path : "/index/hebei/tangshan" , component : TangShan }, { path : "/index/hebei/qinhuangdao" , component : QinHuangDao, } ] }, { path : "/index/shandong" , component : ShanDong, routes : [ { path : "/index/shandong/jinan" , component : JiNan }, { path : "/index/shandong/qingdao" , component : QingDao }, { path : "/index/shandong/yantai" , component : YanTai } ] }, { path : "/index/shanxi" , component : ShanXi } ] } ] } ]; Export default routes Copy the code

github address (using react-router-coinfg):

github.com/baweireact/...

 

Better maintenance after splitting:

Import React, the Component {} from 'REACT' Import {Switch, the Route, the Redirect} from 'REACT-Router-DOM' Import the Login from '../pages/Login' Import ShanDong from '../pages/ShanDong' Import ShanXi from '../pages/ShanXi' import ShiJiaZhuang from '../pages/ShiJiaZhuang' import ZhangJiaKou from '../pages/ZhangJiaKou' import ChengDe from '../pages/ChengDe' import NoFound from '../pages/NoFound' importHeader from '../components/ Header ' import Sidebar from '../components/ Sidebar ' import HeBeiCity from '../components/HeBeiCity' import './index.css' const HeBei = () => { return ( <> < Route > < HeBeiCity > </HeBeiCity > </Route > < Route path = "/index/hebei/shijiazhuang" component = {ShiJiaZhuang} > </Route > < Route path = "/index/hebei/zhangjiakou" component = {ZhangJiaKou} > </Route > <Route path ="/index/hebei/chengde" component = {ChengDe} > </Route > </> ) } const Index = () => { return ( <> < Route > < Header > </Header > < Sidebar > </Sidebar > </Route > < Switch > < Route path = "/index/hebei" component = {HeBei } > </Route > < Route path = "/index/shandong" component = {ShanDong} > </Route > < Route path = "/index/shanxi" component = {ShanXi} > </Route > </Switch > </> ) } export default class Router extends Component { render () { return ( <> < Switch > < Redirect exact from = "/" to = "/login" > </Redirect > < Redirect exact from = "/index/hebei" to = "/index/hebei/shijiazhuang" > </Redirect > < Route path = "/login" component = {Login} > </Route > <Route path ="/index" component = {Index} > </Route > < Route component = {NoFound} > </Route > </Switch > </> ) } } Copy code

github source code:

github.com/baweireact/...

 

12. Use PropTypes for type checking

Reference link: zh-hans.reactjs.org/docs/typech...

 

Thirteen, refs and DOM

Reference link: zh-hans.reactjs.org/docs/refs-a...

Ref is added to Component to obtain Component instance, and added to native HTML is to obtain DOM

The first usage (createRef):

Import React, the Component {} from 'REACT' class the MyComponent the extends the Component { constructor ( The props ) { Super (The props); the this .myRef React.createRef = (); } handleFocus () { this .myRef.current.focus() } componentDidMount () { this .myRef.current.focus() } render () { return ( < div > < input ref = {this.myRef}/> < button onClick = {this.handleFocus.bind(this)} > Get focus </button > </div > ) } } Export default MyComponent copy the code

The second way of writing (callback function):

Import React, the Component {} from 'REACT' class the MyComponent the extends the Component { constructor ( The props ) { Super (The props); } handleFocus () { this .input.focus() } setInputRef ( element ) { this .input = element } componentDidMount () { this .input.focus() } render () { return ( < div > < input ref = {this.setInputRef.bind(this)}/> < button onClick = {this.handleFocus.bind(this)} > Get focus </button > </div > ) } } Export default MyComponent copy the code

The third way of writing (string, obsolete API, don't use it anymore):

Import React, the Component {} from 'REACT' class the MyComponent the extends the Component { constructor ( The props ) { Super (The props); } handleFocus () { this .refs.input.focus() } componentDidMount () { this .refs.input.focus() } render () { return ( < div > < input ref = 'input'/> < button onClick = {this.handleFocus.bind(this)} > Get focus </button > </div > ) } } Export default MyComponent copy the code

The fourth way of writing (the child component passes ref to the parent component):

Parent component:

Import React, the Component {} from 'REACT' Import the Input from '../components/Input.js' class Index extends Component { constructor ( props ) { super (props); } handleFocus () { this .input.focus() } handleSetInputRef ( element ) { this .input = element } componentDidMount () { this .input.focus() } render () { return ( < div > < Input onInputRef = {this.handleSetInputRef.bind(this)} > </Input > < button onClick = {this.handleFocus.bind(this)} > Get focus </button > </div > ) } } Export default Index copy the code

Subassembly:

Import React, the Component {} from 'REACT' class Input extends Component { render () { return ( < div > < input ref = {this.props.onInputRef.bind(this)} > </input > </div > ) } } Export default the Input copy the code

14. ReactDOM

findDOMNode is a method in ReactDOM

ReactDOM.findDOMNode(this) returns the DOM node corresponding to the component instance

Import React, the Component {} from 'REACT' Import ReactDOM from 'DOM-REACT' ; class Index extends Component { constructor ( props ) { super (props); } handleClick () { let dom = ReactDOM.findDOMNode( this ) console .log(dom) } componentDidMount () { } render () { return ( < div > < button onClick = {this.handleClick.bind(this)} > button </button > </div > ) } } Export default Index copy the code

When the parameter of findDOMNode is DOM, the return value is that DOM:

Import React, the Component {} from 'REACT' Import ReactDOM from 'DOM-REACT' ; class Index extends Component { constructor ( props ) { super (props); this .myRef = React.createRef(); } handleClick () { let dom = ReactDOM.findDOMNode( this .myRef.current) console .log(dom) } componentDidMount () { } render () { return ( < div > < input ref = {this.myRef}/> < button onClick = {this.handleClick.bind(this)} > button </button > </div > ) } } Export default Index copy the code

find

15. Mock data

Reference link: github.com/nuysoft/Moc...

 

16. antd

Reference link: ant.design/docs/react/...

 

Seventeen, Context

Reference link: zh-hans.reactjs.org/docs/contex...

index.js:

Import React, the Component {} from 'REACT' Import {ThemeContext} from './theme-context' ; Import Toolbar from '../components/Toolbar.js' class Index extends React . Component { constructor ( props ) { super (props) this .state = { count : 0 } } handleAdd () { let {count} = this .state count = count + 1 this .setState({ count }) } render () { let {count} = this .state return ( < div > < ThemeContext.Provider value = {count} > < Toolbar/> < button onClick = {this.handleAdd.bind(this)} > Add </button > </ThemeContext.Provider > </div > ); } } Export default Index copy the code

theme-context.js:

Import React from 'REACT' Export const ThemeContext = React.createContext ( 'Light' ); duplicated code

Tootbar.js:

Import React, the Component {} from 'REACT' Import ThemedButton from './ThemedButton.js' class Toolbar extends Component { render () { return ( < ThemedButton/> ) } } Export default Toolbar Copy the code

ThemedButton.js:

Import React, the Component {} from 'REACT' Import {ThemeContext} from '../pages/theme-context' ; class ThemedButton extends Component { render () { let value = this .context return ( < div > {value} </div > ) } } ThemedButton.contextType = ThemeContext; Export default ThemedButton copy the code

18. Event system

Virtual DOM exists in the form of objects in memory. It is relatively simple if you want to add events to these objects. React implements a synthetic event layer based on Virtual DOM , and the event we define will receive an instance of a synthetic event object. There will be no compatibility issues with the IE browser, and the event bubbling mechanism is also supported.

The binding method of React events is similar in writing to native HTML event monitoring:

<button onClick={ this .handleClick.bind( this )}></button> Copy code

This is very similar to JavaScript's DOM0 level event, but there are some differences. The following is the DOM0 level event:

< button onclick = "handle()" > </button > Copy code

React does not directly bind event handlers to the DOM like DOM0-level events. React only borrows this way of writing.

At the bottom of React, two things are mainly done for synthetic events: event delegation and automatic binding.

1. Event delegation

React does not bind event handling functions to the current DOM, but binds all events to the outermost layer of the structure , using a unified event listener.
This event listener maintains a mapping to save all the internal event listeners and processing functions of the component.
When the component is mounted and unmounted, only some objects are inserted and deleted on the unified event listener.

2. Automatic binding

In React components, the context of each method will point to an instance of the component, which is automatically bound to this as the current component. And React will cache this kind of reference to achieve the maximum optimization of CPU and memory.
Note: When using es6 class or pure function writing, this kind of binding no longer exists, we need to manually implement this binding.

Bind method: This method can help us bind this in the event handler, and can pass in parameters to the event handler:

class App extends Component { handleClick ( e, arg ) { console .log(e, arg) } render () { return < button onClick = {this.handleClick.bind(this, ' test ')}> </button > } } Copy code

19. Redux

solved problem:

 

principle:

Animation:

 

Twenty, redux-thunk

Source code:

function createThunkMiddleware ( extraArgument ) { return ( {dispatch, getState} ) => next => action => { if ( typeof action === 'function' ) { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk; copy code

Compile into es5:

"use strict" ; Object .defineProperty( exports , "__esModule" , { value : true }); exports .default = void 0 ; function createThunkMiddleware ( extraArgument ) { return function ( _ref ) { var dispatch = _ref.dispatch, getState = _ref.getState; return function ( next ) { return function ( action ) { if ( typeof action === 'function' ) { return action(dispatch, getState, extraArgument); } return next(action); }; }; }; } var thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; var the _default = the thunk; Exports .DEFAULT = the _default; duplicated code

The core concept of Redux is actually very simple: store the state that needs to be modified in the store, initiate an action to describe what happened, and use reducers to describe how the action changes the state tree. When creating a store, you need to pass in the reducer. The store.dispatch API can really change the data in the store.

After dispatching an action, before reaching the reducer, to perform some additional operations, middleware is needed. You can use Redux middleware for logging, creating crash reports, calling asynchronous interfaces or routing, etc. In other words, middleware is an enhancement to store.dispatch().

The usage of middleware:

Import {createstore, combineReducers, applyMiddleware} from 'Redux' Import the thunk from 'the thunk-Redux' Import the reducers from './reducers' const the reducer = combineReducers (the reducers) const Store createstore = (the reducer, applyMiddleware (the thunk)) Export default Store duplicated code

Directly introduce the thunk middleware, put it in the applyMiddleware method, and pass in the createStore method to complete the function enhancement of store.dispatch(). That is, some asynchronous operations can be performed in the reducer.

In fact, applyMiddleware is a native method of Redux, which groups all middleware into an array and executes them in sequence.

Handwriting middleware (logger, thunk):

Import {createstore, combineReducers, applyMiddleware} from 'Redux' Import the reducers from './reducers' const logger = store => next => action => { console .log( 'prev state' , store.getState()) console .log( 'dispatch' , action) next(action) console .log( 'next state' , store.getState()) } const logger2 = store => next => action => { console .log( 'prev state2' , store.getState()) console .log( 'dispatch2' , action) next(action) console .log( 'next state2' , store.getState()) } const myThunk = store => next => action => { if ( typeof action === 'function' ) { return action(store.dispatch) } return next(action) } const the reducer = combineReducers (the reducers) const Store createstore = (the reducer, applyMiddleware (myThunk, Logger, logger2)) Export default Store duplicated code

Reference link: segmentfault.com/a/119000001...

Twenty-one, flex three-stage

<!DOCTYPE html > < html lang = "en" > < head > < meta charset = "UTF-8" > < meta name = "viewport" content = "initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device -width" > < title > Document </title > < style type = "text/css" > html { height : 100% ; } body { margin : 0 ; height : 100% ; } .m-wrap { display : flex; flex-direction : column; height : 100% ; } .m-header { height : 50px ; background : #aaaaaa ; } .m-content { flex : 1 ; background : #dddddd ; } .m-footer { height : 50px ; background : #cccccc ; } </style > </head > < body > < div class = "m-wrap" > < header class = "m-header" > head </header > < main class = "m-content" > main </main > < footer class = "m- footer" > footer </footer > </div > </body > </body > </html > Copy code

22. Xiaomi Book City

github address:

github.com/baweireact/...

Twenty-three, Dangdang

github address:

github.com/baweireact/...

Twenty-four, carousel diagram

github address:

github.com/baweireact/...

Twenty-five, login and component nesting

 

github address:

github.com/baweireact/...

 

Twenty-six, cat's eye

github address:

github.com/baweireact/...

Twenty-seven, shopping cart

 

github address:

github.com/baweireact/...

other

The forceUpdate method enables the component to call its own render() method to re-render the component:

handleUpate () { this .forceUpdate() } Copy code
Receive the specified container parameters in the reactDom.unmountComponentAtNode() method: copy the code

Unloading a component from the DOM will clear its event handlers and state together. If there is no corresponding mounted component on the specified container, this function will do nothing. Will return if the component is removed

true
, If no components can be removed
false
.

handleUnmount () { ReactDOM.unmountComponentAtNode( document .getElementById( 'root' )) } componentWillUnmount () { console .log( 'Before uninstall' ) } Copy code

The synthetic event bound in the component wants to prevent the event from bubbling to the document through e.stopPropagation() How to solve it

e.nativeEvent.stopImmediatePropagation() Copy code