Introduction to the

React is really an amazing and elegant framework. Before I worked on the React project, I was working on Angular. Angular is such a comprehensive and huge framework that it has everything in it at the beginning of the design and is so complex that I don’t need any other auxiliary libraries to work with angular projects. However, the React project is really different. If you only know one React, it is difficult to develop requirements. Because React is all about rendering the UI.

Here is a template for the React project I developed. There are corresponding instances for the requirements encountered in the development process. Technology stack: React + React-router + React-Reselector + Webpack + ES6 + Typescript + sass. Click here to visit

What do I need to know about the React project

react
redux
react-router
webpack
ES6
redux-saga
reselect
react-redux
react-router-redux
react-router-dom
Sass
Less

react

As mentioned earlier react is only responsible for rendering the UI

Starting from the V – dom

One of the most difficult things about React is the idea of a virtual DOM. Here’s a good analogy: Think of dom and JavaScript as two separate islands connected by a bridge, but with tollbooths on the bridge. The more times you use JavaScript to access the DOM islands, the more expensive it becomes. This is the process of javascript manipulating the DOM, and maybe we often hear or see that doing as little as possible with the DOM is performance intensive. But what’s so expensive about DOM manipulation? , here to summarize:

It’s a long process from the input URI to the page loading, so let’s start with parsing the HTML. (1) Parse HTML, start to build the DOM tree; (2) Parse the CSS to generate a CSS rule tree; (3) Merge DOM tree and CSS rule tree to generate render tree; (4) Layout render tree (Layout/reflow), at this time responsible for the element size, position calculation, belongs to js reflux process; ⑤ Draw the render tree (paint), draw the page pixels, belong to the redrawing process; ⑥ The browser will send the information of each layer to the GPU(image processor), and the GPU will composite the layers and display them on the screen. This is the process of initial rendering. After DOM is operated by JS, backflow and redrawing will be caused, and the backflow cost is very high. The backflow of one node will lead to the backflow of sibling nodes and child nodes, which will consume GPU resources all the time.

We started with the cost of manipulating the DOM by introducing React, which creates the virtual DOM and stores it. Whenever the state changes, new virtual nodes are created to compare with the previous ones, and the changed parts are rendered. The whole process does not obtain and operate the DOM. Only when the real render, the real DOM will be operated, thus triggering the rendering of the page.

V – the disadvantage of the dom

ReactJS uses a virtual DOM mechanism that lets front-end developers provide a render function for each component. The render function converts props and state into ReactJS ‘virtual DOM, and the ReactJS framework creates a real DOM of the same structure based on the virtual DOM returned by Render.

Every time state changes, the ReactJS framework recalls the Render function to get a new virtual DOM. The framework then compares the differences between the last generated virtual DOM and the new virtual DOM, and then applies those differences to the real DOM.

There are two big drawbacks:

Render generates a complete virtual DOM for each state change, even if the state change is small.
// The render function is also evaluated in its entirety. If the render function is complex, this process will waste a lot of computing resources.

// The process by which the ReactJS framework compares virtual DOM differences is slow and error-prone. For example, if you want to insert an item 
  • at the top of a
      list,
  • // Then the ReactJS framework will assume that you changed each of the
  • items in
      and insert a
    • at the end.
  • Copy the code

    This is because the old and new virtual DOMs received by ReactJS are independent of each other, and ReactJS does not know what is happening to the data source. It can only guess what action to perform based on the old and new virtual DOMs. Automatic guessing algorithms are both inaccurate and slow, The front-end developer must manually provide the key attribute, shouldComponentUpdate method, componentDidUpdate method, or componentWillUpdate method to help the ReactJS framework guess correctly.

    The diff algorithm

    Where does React’s Diff algorithm come in? When the component is updated, React creates a new virtual DOM tree and compares it to the previous stored DOM tree. This comparison process uses diff algorithm, so it is not used when the component is initialized. React hypothesizes that the same nodes have similar structures, while different nodes have different structures. If the corresponding nodes are found to be different, the old node and all its children are directly deleted and replaced with the new node. If it is the same node, only the property changes are made.

    List for diff algorithm is slightly different, because the list is usually has the same structure, in the node list to delete, insert, sorting, the overall operation of a single node is much better than contrast one by one by one to replace, so in creating a list you need to set up the key value, so the react to distinguish who is who. Of course, not writing the key is fine, but this will usually give us a warning telling us to add the key to improve react performance.

    For more information about diff source code, please refer to source code parsing!

    Single data stream

    componentization

    A component is a view module with independent functions. The biggest advantage of React lies in that its functions are componentitized and it follows the principle of maintainable front end.

    Component life cycle

    Five hook functions that are fired when the component initializes

    1.getDefaultProps()

    Set the defaultProps. You can also use defaultProps to set the default properties of the component.

    Static static props = {}

    2.getInitialState()

    There is no such hook function when using es6’s class syntax. You can define this.state directly within constructor. At this point, you can access this.props.

    GetInitialState = constructor ();}

    The react.createclass function will only work if the component class is created using the React.createclass method, and the react.createclass method is officially deprecated by Fb, so I won’t go into details here.

    3.componentWillMount()

    It is called only when the component is initialized, not later when the component is updated, and only once during the entire lifecycle when the state can be changed.

    4.render()

    The most important steps of React, creating the virtual DOM, performing the DIff algorithm, and updating the DOM tree, all take place here.

    Render () is supposed to be a pure function that returns the result based entirely on the state and props, with no side effects, so calling setState in render is wrong because pure functions should not cause state changes

    5.componentDidMount()

    Called after the component is rendered, you can get and manipulate the DOM node through this.getDomNode () and call it only once.

    The prefix did indicates a call after entering a state, such as componentDidMount, where data requests are typically made during component initialization.

    Why is the request data called in this hook function?

    See the answers to some questions I encountered in React for my summary

    Five hook functions that are fired when a component interacts with an update

    6.componentWillReceiveProps(nextProps)

    This is not called when the component is initialized. It is called when the component accepts new props.

    During development, you usually change the state in this hook function. Changing the state in this method is not a second rendering, but a state merge.

    7.shouldComponentUpdate(nextProps, nextState)

    React performance optimization is very important. If the two props and state are the same as each other, return false to prevent the update, because the same property state must generate the same DOM tree. This eliminates the need to create a new DOM tree and diff the old DOM tree, saving a lot of performance, especially if the DOM structure is complex. However, calling this.forceUpdate skips this step.

    8.componentWillUpdate(nextProps, nextState)

    Not called when the component is initialized, but only when the component is about to be updated.

    Never call this.setState() in this function. It will cause a circular call.

    9.render()

    Similar to render(), create the virtual DOM, diff algorithm, update the DOM tree are done here.

    10.componentDidUpdate()

    Not when the component is initialized, but when the component is updated, when the DOM node can be obtained.

    The updated this.state can be obtained after componentDidUpdate. If you want to get the default props for the component and assign it to State, you can change it here to achieve the UI effect.

    Called when a component is uninstalled

    10.componentWillUnmount()

    Called when the component is about to be uninstalled, some event listeners and timers need to be cleared at this time, and the value on the store of the component is also clear.

    ComponentWillUnmount Performs resets all related parameters. Calling setState in this method does not trigger Render because the update state is reset to NULL for all update queues.

    // The data must be written to the Reducer
    this.props.clearPointData();
    
    [CLEAR_POINT_DATA]: (state, action: Action<any>) = > {
        return Object.assign({}, state, {
            selectedReadingList: {},
            knowledgePoint: {},}); }Copy the code

    It can be seen from the above that React has a total of 10 periodic functions (render is repeated once). These 10 functions can meet all our requirements for component operation, and good utilization can improve development efficiency and component performance.

    react-router

    When there are many pages, the project will get bigger and bigger. Especially for single-page applications, the first rendering will be very slow. In this case, you need to load on demand and only load the corresponding JS file when you switch to the page. The Route component is changed to getComponent, the component is obtained in require.ensure mode, and the chunkFilename is configured in WebPack.

    const chooseProducts = (location, cb) = > {
        require.ensure([], require => {
            cb(null.require('.. /Component/chooseProducts').default)
        },'chooseProducts')}const helpCenter = (location, cb) = > {
        require.ensure([], require => {
            cb(null.require('.. /Component/helpCenter').default)
        },'helpCenter')}const saleRecord = (location, cb) = > {
        require.ensure([], require => {
            cb(null.require('.. /Component/saleRecord').default)
        },'saleRecord')}constRouteConfig = (<Router History ={history}> <Route Path ="/" Component ={Roots}> <IndexRoute Component ={index} />// home page <Route path="index" component={index} /> <Route path="helpCenter" getComponent={helpCenter} />// helpCenter <Route Path ="saleRecord" getComponent={saleRecord} /> </Route> </Router>);Copy the code

    react-router-redux

    The route is synchronized with the application state. The react-router-Redux library can coordinate the two libraries. The react-Router-Redux library can coordinate the react-Router-Redux library and the React-Router-Redux library.

    react-router-dom

    .

    redux

    Communication between components

    React promotes one-way data flow, where data is passed from top to bottom, but communication between components that are either bottom-up or not on a data stream becomes complicated. There are many ways to solve the communication problem. If it is just a parent-child relationship, the parent can pass a callback function as an attribute to the child, and the child can call the function directly to communicate with the parent.

    The component hierarchy is nested so deep that you can use the context getChildContext to pass information so that children of any of the layers can be accessed directly through this.context without having to pass functions down the hierarchy.

    Sibling components cannot communicate directly with each other, they can only use their superiors on the same layer as a relay station. If the sibling components are all top-level components, in order for them to communicate, they have to have another layer of components on top of them. This layer of components holds data and transmits information, which is what Redux does.

    Information between components can also be passed through global events. Different pages can pass data through parameters, and the next page can be retrieved using location.param. Actually react itself is very simple, but the hard part is how to realize data communication between components in an elegant and efficient way.

    redux

    First of all, redux is not necessary. It acts as an additional component on top of the top layer components to perform logical operations, store data, and implement communication between components, especially the top layer components. If there is not much communication between the components, the logic is not complex, and the view is simply rendered, then use the callback, the context, not the redux, it will affect the development speed. However, if the components communicate very frequently and the logic is complex, the advantages of Redux are particularly obvious. When I first worked on the React project, I didn’t use Redux, all the logic was implemented inside the components. At that time, I wrote more than 800 lines of code to implement a shopping cart with complicated logic. When I looked back, I didn’t know what I had written, the picture was so touching.

    A little bit about how Redux and React work together. React-redux provides connect and Provider, which connect components to redux and store components to redux. The component sends the action through the Dispatch. The Store calls the corresponding Reducer based on the action type attribute and passes the state and the action to the reducer. The Reducer processes the state and returns a new state to the Store. Connect listens for changes in the store, calls setState to update the component, and the component’s props change.

    The process looks like this:

    It is worth noting that connect, the Provider, mapStateToProps mapDispatchToProps is the react – story, the story itself and the react didn’t have anything to do, it’s just a data processing center, and react to produce no coupling, It’s the React-Redux that keeps them together.

    Redux and React-Redux are implemented in different ways.

    Let’s do a picture

    It’s obviously more complicated than the first one, but they’re saying the same thing. Analyze slowly from the top down:

    Let’s start with redux:

    Redux consists of three parts: Store, Reducer, and Action.

    A store is an object that has four main methods:

    1, the dispatch:

    For action distribution —- In a createStore, we can use middleware to modify dispatchs. for example, when an action is sent to a dispatch, the Reducer will be triggered immediately. Sometimes we don’t want it to be triggered immediately. Instead, wait for the asynchronous operation to complete before triggering, this time use redux-Thunk to transform the dispatch, previously can only pass an object, after the transformation can pass a function, in this function we manually dispatch an action object, the process is controllable, the implementation of asynchronous.

    2, the subscribe:

    —- This function registers a listener to listen for state changes when the store calls Dispatch. This function can be called when we need to know if state has changed. It returns a function that calls the returned function to unregister the listener. Let unsubscribe = store.subscribe(() => {console.log(‘state changed ‘)})

    3, getState:

    Obtain the state—- in the store. When we use the Action to trigger the Reducer to change the state, we need to obtain the data in the new state again. After all, the data is what we want. GetState is mainly used in two places. First, after the Dispatch gets the action, the Store needs to use it to obtain the data in the state and transfer the data to the Reducer. This process is automatically executed. The second is when we use subscribe to listen to the change of state to call it to get the new state data, if we do this step, we have succeeded.

    4, replaceReducer:

    Replace the Reducer and change the state logic.

    action:

    An action is an object in which the type attribute is required and some data can be passed. Actions can be created using actionCreactor. To dispatch is to send an Action object.

    reducer:

    Reducer is a function that accepts a state and an action and returns the new state based on the type of the action. There are many objects in the state tree. Each state object corresponds to a Reducer. The name of the state object can be defined during the merge.

    It looks like this:

    const reducer = combineReducers({
         a: doSomethingWithA,
         b: processB,
         c: c
    })
    Copy the code

    combineReducers:

    It takes the entire state and an action, and then distributes the entire state to the corresponding reducer. All the reducers receive the same action, but they decide based on the type of action. If it has this type, it will process it and return the new state, if it doesn’t, it will return the default value, and then the scattered states will be put together to return a new state tree.

    We call store.Dispatch and pass in the action. We use getState to get the current state tree and register a SUBSCRIBE listener to listen for changes. Then call combineReducers and pass in the obtained state and action. CombineReducers will pass the incoming state and action to all reducer, return the new state according to the action type, and trigger the update of the state tree. So we call subscribe and we listen for the change of state and we use getState to get the new state.

    Redux state and React state are completely unrelated, except for the same name.

    What does react-Redux do?

    react-redux

    If only redux is used, the process looks like this:

    component –> dispatch(action) –> reducer –> subscribe –> getState –> component

    Here’s what happens when you use React-Redux:

    component –> actionCreator(data) –> reducer –> component

    The three functions of the Store: Dispatch, subscribe, and getState do not need to be written manually. React-redux does this for us, and it also offers two great gay friends Provider and Connect.

    A Provider is a component that accepts the Store as props and then passes it down through the context, so that any component in react can get the Store through the context. This means that we can use dispatch(action) in any component to trigger the reducer to change state, and subscribe to listen for the change of state, and then use getState to obtain the changed value. This is not recommended, as it can lead to data flow chaos, excessive coupling can affect component reuse, and is more difficult to maintain.

    Connect –connect(mapStateToProps, mapDispatchToProps, mergeProps, options) is a function that takes four arguments and returns one more function –wrapWithConnect, WrapWithConnect accepts a component as an argument wrapWithConnect(Component), which internally defines a new component Connect(container component) and returns the incoming component (UI component) as a child of Connect.

    So the complete way to write it is: connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(Component)

    MapStateToProps (state, [ownProps]) :

    MapStateToProps takes two arguments, the store’s state and the custom props, and returns a new object that is passed to the UI component as part of the props. We can custom return an object based on the data required by the component. A change in ownProps also triggers mapStateToProps

    function mapStateToProps(state) {
       return { todos: state.todos };
    }
    Copy the code

    MapDispatchToProps (dispatch, [ownProps]) :

    MapDispatchToProps, if they are objects, are passed to the UI component as part of the props binding with the Store. If it is a function, and it takes two arguments, bindActionCreators will bind the action with the Dispatch and return an object, which will be passed to the UI component with the ownProps as part of the props. So whether mapDispatchToProps is an object or a function, it will eventually return an object, and if it is a function, the key value of that object is customizable

    function mapDispatchToProps(dispatch) {
       return {
          todoActions: bindActionCreators(todoActionCreators, dispatch),
          counterActions: bindActionCreators(counterActionCreators, dispatch)
       };
    }
    Copy the code

    MapDispatchToProps returns objects whose properties are actually ActionCreators, which are bound to Dispatch, so when called actionCreator will immediately send the action instead of sending it manually. A change in ownProps also triggers mapDispatchToProps.

    MergeProps (stateProps, dispatchProps ownProps) :

    Combine the objects returned by mapStateToProps() and mapDispatchToProps() and the component’s own props into a new props and pass it to the component. Assign ({}, ownProps, stateProps, dispatchProps).

    The options:

    Pure = true indicates that the Connect container component will make a shallow comparison between the state and ownProps of the store in shouldComponentUpdate to determine whether the changes have occurred and optimize the performance. False does not compare.

    The connect function doesn’t actually do anything. Most of the logic is implemented in the function it returns, wrapWithConnect, or rather in the Connect component defined in wrapWithConnect.

    Here is a complete react –> redux –> react process:

    The Provider component accepts the Store of Redux as props and passes it down through the context.

    2. Connect binds mapDispatchToProps to the store when the connect function is initialized. If mapDispatchToProps is a function, then after the connect component gets the store, With the passed store.dispatch and action, bind with bindActionCreators and return the object with the store, connect will return a wrapWithConnect function, WrapWithConnect is called and passed in a UI Component. WrapWithConnect defines a Connect Component internally using the Class Connect extends Component. The incoming UI Component is a child of Connect. The Connect component then gets the store from the context and the full state object from the store.getState, If we pass state to mapStateToProps and return stateProps, mapDispatchToProps, or mapDispatchToProps we’ll return a dispatchProps, The props of the stateProps, dispatchProps, and Connect components are passed to the UI component via object.assign (), or mergeProps combined as props. Then call store.subscribe in ComponentDidMount, and register a callback function handleChange to listen for state changes.

    And then the UI component can find actionCreator in props, and when we call actionCreator we’ll automatically call Dispatch, and from dispatch we’ll call getState to get the whole state, At the same time, register a listener to listen for the changes in state. Store passes the obtained state and action to combineReducers. CombineReducers will pass the state to the subreducer respectively according to the key value of state. The reducer will be executed one by one to determine the action type. If action type exists, the reducer will return a new state. If no action type exists, the reducer will return the default state. CombineReducers again merges the single state returned by the sub-reducer into a new complete state. Now the state changes. Once state returns a new value, Dispatch calls all registered listener functions, including handleChange. Inside handleChange, it first calls getState to get the new value and makes a shallow comparison between the old and new states. If they are different, the system calls mapStateToProps to obtain stateProps and compares the old and new stateProps. If they are the same, the system returns the props directly and no further operations are performed. If not, call this.setstate () to trigger the Connect component update, pass in the UI component, trigger the UI component update, at this point UI component gets the new props, react –> redux –> react a process is finished.

    The above is a bit complicated, but the simplified version of the process is:

    The Provider component accepts the Store of Redux as props and passes it down through the context.

    MapStateToProps (), mapDispatchToProps (), and component (), and passes state and actionCreator () to the component as props. In this case, the component can call actionCreator to trigger the Reducer function to return the new state. Connect listens to the state change and calls setState to update the component and pass the new state into the component.

    Connect can be written very concisedly. MapStateToProps, mapDispatchToProps are just callbacks passed in. Connect will call them if necessary, and the names are not fixed or even unnamed.

    Simplified version:

    connect(state= > state, action)(Component);
    Copy the code

    redux-saga

    To be updated…

    reselect

    When we first started the React program, we didn’t worry about the cost of the render loop. But when our UI gets complicated, we need to consider this. React provides tools that allow us to hijack the render loop so that if the render seems unnecessary, we can use tools to prevent rerendering from happening. To do this, we type in the componentShouldUpdate lifecycle event, which returns a Boolean that tells the component whether or not it should be updated. This is based on PureRenderMixin, which compares the input props and state to the previous props and state and returns false if they are equal.

    Unfortunately, that’s it.

    Reselect a library of memorized selectors. Selectors are defined as functions that retrieve some part of the Redux state. Using memory power, we can organize unnecessary rerendering and computation of derived data, thus speeding up our app.

    Reselect middleware addresses the issue of how to reduce rendering stress when state changes during component interactions. A caching mechanism is used in Reselect

    “Selector” is a simple Redux library

    • The Selector can compute the derived data, and you can make the Redux store as little state as possible.
    • Selectors are efficient, and they only compute when a parameter changes.
    • Selectors can be combined, they can be passed as input to other selectors.

    reference

    – Use Reselect to improve React and Redux program performance

    ES6

    Introduction to ES6 by Mr. Ruan Yifeng

    ES6 adds a lot of things to ES5, just to name a few common ones: use let const and completely discard var; Template import and export (import,export); String extensions (‘ ‘,${}); Object extensions (structure assignment, new apis such as assgin(),keys(),is(), etc.; Array extensions (struct assignment,from(),of(),findIndex(),find(), etc.); Extensions to functions (function arguments can set default values, arrow functions, no Arguments objects, etc.) Used for traversal (for of,forEach,for in,map, etc.); Used to address asynchrony (generator functions, promise, async/await functions, etc.); The class and extends keywords

    Many of the same ES6 techniques can be implemented with ES5, but ES6 is much more efficient, the code is much more elegant, and there are various packaging tools that can turn ES6 into ES5 for lower browsers, so it’s recommended.

    webpack

    Refer to the webpack website

    Sass or Less

    As the front end continues to evolve, the complexity of web pages continues to increase, native CSS has become too much for developers to handle, and preprocessors have given us the power. CSS Preprocessors: Why use Preprocessors?

    Sass

    See Sass syntax

    Less

    Refer to Less syntax

    ===================================end==================================

    React Prepare

    Finally attached react technology stack related links, hope to help you!

    react

    React Introduction example tutorial

    • www.ruanyifeng.com/blog/2015/0…

    React Technology stack series tutorial

    • www.ruanyifeng.com/blog/2016/0…

    The react components

    React creates components in three ways and their differences

    • www.cnblogs.com/wonyun/p/59…

    The importance of React component splitting from a performance perspective

    • www.cnblogs.com/libin-1/p/6…

    The react performance report

    React performance optimization summary

    • Segmentfault.com/a/119000000…

    Modern Web Development –React

    • Github.com/wxyyxc1992/…

    9 things to know for starters in React.js

    • www.iteye.com/news/31748

    react router

    React Router Tutorial

    • www.ruanyifeng.com/blog/2016/0…

    redux

    Redux Introduction Tutorial (1) : basic usage

    • www.ruanyifeng.com/blog/2016/0…

    Redux Tutorial ii: Middleware and asynchronous operations

    • www.ruanyifeng.com/blog/2016/0…

    Redux Introduction tutorial (3) : React-redux usage

    • www.ruanyifeng.com/blog/2016/0…

    Redux Chinese documents

    • www.redux.org.cn/

    Redux English documents

    • redux.js.org/

    Redux core concept

    • www.jianshu.com/p/3334467e4…

    React react-Redux connect method

    • Yq.aliyun.com/articles/59…

    redux-saga/redux-thunk

    Saga Chinese Document

    • Redux-saga-in-chinese.js.org/docs/api/in…

    Let’s talk about redux-Saga of redux asynchronous streams

    • www.jianshu.com/p/e84493c7a…

    Redux-saga practical refers to north

    • Juejin. Im/post / 684490…

    Reselect

    • www.jianshu.com/p/6e38c6636…
    • Baijiahao.baidu.com/s?id=156195…

    Others

    Introduction to Flux architecture

    • www.ruanyifeng.com/blog/2016/0…

    Immutable

    • Segmentfault.com/a/119000000…

    dom diff

    • calendar.perfplanet.com/2013/diff/

    The meaning and usage of Generator functions

    • www.ruanyifeng.com/blog/2015/0…