1. What is the virtual DOM and how is it formed

The virtual DOM is an in-memory representation of the real DOM. Simply put, the virtual DOM is an object consisting of tags,props, and children

  <div id="app">
    <p class="text">hello world!!!</p>
  </div>

  // can be converted to the following virtual DOM representation
  {
    tag: 'div'.props: {
      id: 'app'
    },
    chidren: [{tag: 'p'.props: {
          className: 'text'
        },
        chidren: [
          'hello world!!! ']]}}Copy the code

The object above is what we call the virtual DOM, which can be represented as a tree structure. The native DOM is expensive to create even an empty DIV because browser vendors need to implement so many specifications (various HTML5 attributes, DOM events). The point at which the virtual DOM improves performance is that when the DOM changes, the diff algorithm is used to compare JavaScript native objects, calculate the DOM that needs to be changed, and then only work on the changed DOM, rather than updating the entire view

react

React uses Babel to convert JSX into an H function: The react_createElement function, followed by the render function, inserts the virtual DOM into the htmlDOM tree to render the page. The sample code compiles JSX with Babel and converts it into a structure that React can handle


  const Page = () = > {
    return <div 
            className="levi"
            style={{margin: '100px'}} 
            onClick={onClick}
            >hello world</div>
    }

  export default Page

  // Babel is compiled
  const Page = () = > {
    return /*#__PURE__*/_react.default.createElement("div", {
      className: "levi".style: {
        margin: '100px'
      },
      onClick: onClick
    }, "hello world");
  };

  var _default = Page;
Copy the code

2. Talk about your understanding of the DIFF algorithm

As the name suggests: is the optimization strategy of comparing old and new VDOM changes and updating the changed parts to the view diff

  • For tree diff optimization, React ignores the movement of DOM nodes across hierarchies
  • For component diff optimization, different components are generated if they are different, so different components are marked for modification rather than detailed comparison
  • A group of child nodes at the same level can be distinguished by corresponding keys
tree diff

If a node does not exist, then the node will not be compared with its children. React only considers the position changes of nodes at the same level, while for nodes at different levels, only creation and deletion are required. If A child node A is found missing, the child node A is destroyed.

component diff

If it is of the same type, the virtual DOM tree is compared, and if it is not, the component is marked as dirty, replacing all child nodes under the entire component. React uses shouldComponentUpdate to determine whether this component needs diff operation. Once React determines that D and G are different types of components, it will not compare their structures. Instead, remove componentD and recreate component G and its children

element diff

When nodes are at the same level, diff provides three node operations: insert, move and delete, as shown in the figure below. The order of old set nodes is A, B, C, D, and the order of new nodes is B, A, D, and C. If it is A traditional diff operation, it will compare the old A with the new B and find that B! =A creates and inserts B into the latest collection, deletes A from the old collection, and so on.React proposed that a group of children at the same level can be determined by keys. If it’s the same node, just move itReact uses keys to distinguish components. The same key indicates the same component. React does not re-create component instances, only updates them. If the key is different, React destroys the existing component instance and creates a new one

3. What are the life cycles

React > latest life cycle for version 16.3,

Removed 3 life cycles

  • componentWillMount
  • componentWillReciveProps
  • componentWillUpdate

Two new life cycles have been added

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

We break the React lifecycle into three phases, respectively

  • Mount phase Mouting
  • Update phase
  • UnMount phase unMount
Mount the stage

The component initialization phase, which is executed only once, has the following lifecycle methods, in the following order

  • constructor
  • staic getDerivedStateFromProps
  • render
  • componentDidMount

If the constructor is used, you need to execute super(props) internally, otherwise an error will be reported.

Constructors often do two things

  • Initialize the state object
  • Custom events (synthetic events) bind this
  class Levi extends React.Component{
    constructor(props) {
      super(props);
      
      this.handleClick = this.handleClick.bind(this); }}Copy the code

GetDerivedStateFromProps Static method of the React instance. This cannot be used in this method and takes two arguments: Even if getDerivedStateFromProps(nextProps, prevState) returns an object to update the current state, if null is returned, the state is not updated

  class Levi extends React.Componet {
    state: {
      age: 20
    }

    static getDerivedStateFromProps(nextProps, prevState) {
      if(nextProps.currentRow ! == prevState.lastRow) {return {
            lastRow: nextProps.currentRow
        }
      }

      return null}}Copy the code

Render React is a pure function that returns elements that need to be rendered. Do not use this method to contain business logic, such as data requests, which may result in repeated rendering and page freezes

ComponentDidMount is called after the componentDidMount component is decorated, and is often used for data requests to retrieve and manipulate the DOM. You can write some subscriptions, but remember to unsubscribe at componentWillUnMount

Update the stage

This phase is triggered when the props and state of the component change

  • getDevrvedStateFromProps
  • shouldCompoentUpdate
  • render
  • getSnapShotBeforeUpdate
  • componentDidUpdate

GetDevrvedStateFromProps ditto

ShouldCompnentUpdate shouldCompnentUpdate(nextProps, nextState) should return a Boolean, true means to perform the update, render the page, False indicates that the page will not render, and returns true by default

Note that this method is not triggered when we call forceUpdate. It is not recommended to write shouldCompnentUpdate logic by hand, unless it involves complex depth comparisons. PureComponent< shallow comparison props,state>

Render ditto

GetSnopShotBeforeUpdate this method comes after Render and before componentDidUpdate, which allows your component to capture some information (such as scroll position) from the DOM before possible changes. There are two arguments: getSnapShotBeforeUpdate(prevProps, prevState), the function returns a value that is passed to componentDidUpdate as the lower three arguments. If no value is returned, return null, otherwise the console will be warned, and componentDidUpdate must not be missing, otherwise it will be warned.


    / / limit chat bubble box scrollTop: https://kinyaying.github.io/webpack-optimize/dist/#/snapshotSampleOptimize
  class Levi extends React.Componet {
    getSnapshotBeforeUpdate(prevProps, prevState) {
      state =  {
          newList: []
      }

      leviRef = React.crateRef();

      if (prevProps.list.length < this.state.newList.length) {
        return this.leviRef.scrollHeight;
      }

      return null;
    }

    componentDidUpdate(prevProps, prevState, perScrollHeight) {
      if(! snopShot) {console.log('Here's getSnapShotBeforeUpdate to get the return value')
        
        const curScrollTop= this.leviRef.scrollTop;
        if (curScrollTop < 5) return ;
        this.leviRef.scrollTop = curScrollTop + (this.rootNode.scrollHeight  - perScrollHeight);   // Add the increased div height, which is equivalent to not moving}}}Copy the code

ComponentDidUpdate occurs after getShapShotBeforeUpdate and accepts 3 parameters divided into: ComponentUpdate (prevProps, prevState, snapshot) DOM manipulation and data requests can be performed in this function, but note that if setState Be sure to write if judgment logic, otherwise it will cause an endless loop and the page will freeze

Refer to the article

  • React 17 Lifecycle Summary
Unloading phase
  • componentWillUnmount

ComponentWillUnmount Is called when a component is unmounted. You can unsubscribe, clear timers, and clear data referenced by stores in components

4、 setState

  • SetState is “asynchronous” only in synthesized events and hook functions, and synchronous in both native events and setTimeout
  • The “asynchronous” of setState does not mean that it is internally implemented by asynchronous code, in fact, the process and code itself are synchronous, but the call order of the synthesized event and hook function is before the update, so that the updated value cannot be immediately obtained in the synthesized event and hook function, which forms the so-called “asynchronous”. Of course, the callback in the second parameter setState(partialState, callback) can get the updated result
  • In “asynchronous”, if the same value is setState multiple times, the setState batch update policy will overwrite it and take the last execution. If multiple different values are setState at the same time, It will be updated in merge batch when updated

SetState is updated using enqueueUpdate. How does enqueueUpdate update state? Keep going down.

EnqueueUpdate If a component is currently being created/updated, it does not update the component immediately. Instead, it puts the current component in the dirtyComponent first. Otherwise, execute batchedUpdates to batch update components;

enqueueSetState: function(publicInstance, partialState, ...) {
  var internalInstance = getInternalInstanceReadyForUpdate(publicInstance);
  if(internalInstance) { (internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = [])).push(partialState), enqueueUpdate(internalInstance); }}function enqueueUpdate(component) {
 // ...  
 if(! batchingStrategy.isBatchingUpdates) { batchingStrategy.batchedUpdates(enqueueUpdate, component);return;
  }

  dirtyComponents.push(component);
}
Copy the code

The “asynchronous” of setState does not mean that it is internally implemented by asynchronous code, in fact, the process and code itself are synchronous, but the call order of the synthesized event and hook function is before the update, so that the updated value cannot be immediately obtained in the synthesized event and hook function, which forms the so-called “asynchronous”. Of course, the callback in the second parameter setState(partialState, callback) can get the updated result

Refer to the article

  • SetState Asynchrony, synchronization and progression
  • How much do you know about React setState? # 11

5. Class components and function components

Class components are commonly known as class components, with declared cycles and state functional components: non-declared cycles, acceptable functions, commonly used as UI components,

Functional components have higher performance than class components and are suitable for the presentation layer. Class components contain declaration cycles and state features to handle complex logic and are suitable for the logical layer. React initially favored functional components for faster rendering. Hooks came out of nowhere

React ref

You can’t use the ref attribute on function components because they don’t have instances.

  • Refs is used when dealing with DOM elements such as focus, text selection, media playback, third-party DOM library integration, and element width and height. React has no control over these situations, so ref is used

  • How to create a ref

    <! -- react createRef -->class Levi extends React.Component {
      constructor(props) {
        this.leviRef = React.createRef();
      }
    
      private init() {
        console.log(this.leviRef)
      }
    
      render() {
        return <div ref={this.leviRef}>hello world</div>;
      }
    }
    
    <!-- hooks -->
    const Page = () = > {
      const leviRef = useRef(initialVal);
    
      const fetch = useCallback(() = > {
        console.log(leviRef.current)
      }, [])
    
      return  <div ref={this.leviRef}>hello world</div>;
    }
    Copy the code
  • Access to the ref

When a ref is passed to the render element, a reference to that element is available in current in the ref

const ref = this.leviRef.current

7. What are higher-order components?

Higher-order components can take functions of react components as arguments and return a new component. Higher-order components can be used in the following scenarios

  • Code reuse, logic abstraction
  • Rendering hijacked
  • Props,
  • State Abstract, operation
  • An instance of this component can be accessed through ref

const HOCComponent = (WrapComponent) = > {
  return class HOCComponent extends React.Component {
      state = {
        name: 'levi'.age: 20
      }
      levi = React.createRef();

      componentDidMount() {
        console.log(this.levi.current); // Prints the component instance
        this.setState({age: 21}) // fecth data
      }

      render() {
        const newProps = {
          area: 'sh'
        }

        // Play the role of permission control, no longer every month page inside the judgment
        if(this.state.age < 18) {
          return <div>Minors have no access</div>
        }

        return <div><WrapComponent {. newProps} {. state} ref={this.levi} /><div>
      }
  }
}
Copy the code

8. What is JSX

  • Advantages, features

    • Enhanced readability
    • The syntax is very similar to HTML
    • Allows customization of tags and components
    • Abstract readability. React is updated without changing any JSX code
    • Modularity ensures that labels in components are separated from business logic
  • Differences between JSX and HTML

    • JSX can use variable properties
    • Events should be written in camel shape
    • HTML uses class, while JSX uses className
    • Style CSS properties are written in camel form
  • What will JSX experience, what will it look like, and how will it render to the page

JSX is constructed by bable compilation +react.js, which turns it into a JS object (the virtual DOM), then creates the DOM element with reactdom.render, and inserts the DOM into the browser

  • Why should JSX go through a layer of Bable compilation?

JSX is an abstract syntax that, when compiled by Bable, can be turned into an object that describes the UI. We can take this object, render it to a browser, or optionally display it to a mobile APP. So why split the React-DOM out

9, What is React.Context

Context provides a way to share values between components without having to pass props through each level of the tree. Advantages: Cross-component access The React component tree shouldComponentUpdate returns false. When the context is updated, it does not cause any child components to update

When the function component react. useContext is updated with the most recent < myContext. Provider> at the upper level, the Hook triggers a rerender and uses the latest context value passed to the MyContext Provider. Even if the ancestor uses React. Memo or shouldComponentUpdate, it will be rerendered when the component itself uses useContext

How to create
  // Create a context, which can be separately extracted into a file
  const LeviInfoContext = React.createContext({ name: 'levi'.age: 20.run: () = > console.log('run')});// Provide the provider containing the component consumption, which accepts a default value value
  class App extends React.Component {
    public render() {
      return (
        <LeviInfoContext.Provider value={{ name: 'levi', age: 21}} >
          <App />
        </LeviInfoContext.Provider>); }}// Class components use consemer consumption
  import LeviInfoContext from 'xxxx';
  class Children extends React.Component {
    public render() {
      return <LeviInfoContext.consumer>{(baseObject) => <div>i am child</div>}</LeviInfoContext.consumer>; }}// Function components use React. UseContext. Accept the value returned by React. CreateContext
  const Page = () = > {
    const info = React.useContext(LeviInfoContext);

    return <div>11111{info.name}</div>;
  };
Copy the code

React performance optimization from Context source code implementation

10. How to avoid component repetition

React is a common problem with duplicate rendering. React provides two methods to avoid duplicate rendering

  • React.Memo(component, fn)
  • React.PureComponent
  • React.useMemo(fn: () => Component, deps)

  const ComponentByMemo = React.memo(compoennt, (prevProps, nextProps) = > {
    // If props is equal, the default callback function returns true and does not update; If props are not equal, false is returned, and the component is updated
    // This is the opposite of the return value of shouldComponentUpdate. ShouldComponent returns true to update, but not to update})class Levi extends React.PureComponent {
    render() {
      return <div>levis</div>}}const ComponentByUseMemo = React.useMemo()

Copy the code

How to improve React performance

  • The use of appropriate shouldComponentUpdate/React. Memo, avoid unnecessary to render the child component
  • Use keys in lists and tables to make React render updates faster
  • Extract common code into a separate file and use route lazy loading

Complementary front-end performance optimization

  • Reduce HTTP requests and cache relevant Ajax data
  • Picture optimization, compression picture
  • CSS optimization, extract common CSS code
  • Js optimization, extract common JS code –
  • Using the CDN content delivery network,
  • Use response packaging tools: Webpack,gulp zip code
  • DOM rendering optimization. Redraw doesn’t necessarily cause backflow, but backflow does redraw, so when you do DOM render, there’s too much backflow and redraw

12. What is React.Fiber

React Event system

14. React Why introduce hooks

  • The logic between components is complex and difficult to use
  • Large components are hard to break down
  • Unintelligible class syntax, forget the event binding this, no solid syntax proposal

In contrast to class components, functional components are too crude, with no lifecycle hooks and no state for class components. But functional components are easy to use, friendly and intuitive

  import React, {useState} from 'react';

  const Levi = () = > {

    const [count, setCount] = useState<number>(0);

    const handleClick = useCallback(() = > {
      setCount(count+1)}, [])return <Button onclick={handleClick}>Click on the</Button>
  }

Copy the code

15. Hooks are frequently used

  • UseState () status hook. Provides internal state for function components
      const Page = () = > {
        const [name, setName] = useState<string>('levi')};Copy the code
  • UseContext () shares the hook. The hook is used to share state between components. React passes data layer by layer through the Porps. It accepts the result of react. CreateContext () as an argument
      const Page = () = > {
        const info = React.useContext(LeviInfoContext);
    
        return <div>11111{info.name}</div>;
      };
    Copy the code
  • UseReducer () status hook. The Action hook. UseReducer () provides state management. The basic principle is that users initiate actions in the page and change state through the Reducer method, so as to achieve the communication between the page and state. Use is much like Redux
      const initialState = { count: 0 };
    
      function reducer(state, action) {
        switch (action.type) {
          case 'increment':
            return { count: state.count + 1 };
          case 'decrement':
            return { count: state.count - 1 };
          default:
            throw new Error();
        }
      }
    
      function Counter() {
        const [state, dispatch] = useReducer(reducer, initialState);
        return (
          <>
            Count: {state.count}
            <button onClick={()= > dispatch({ type: 'decrement' })}>-</button>
            <button onClick={()= > dispatch({ type: 'increment' })}>+</button>
          </>
        );
      }
    Copy the code
  • UseEffect () Side effect hook. It takes two parameters, the first is the asynchronous operation to be performed, and the second is an array that gives the Effect dependencies
      const Page = () = > {
        useEffect(() = > {
          const initial = async() = > {// fetch data
            await Promise.resolve(); }}, [])return <div>11111{info.name}</div>;
    };
    Copy the code
  • UseRef () gets the instance of the component; To store shared data between render cycles (state cannot store data across render cycles because saving state triggers component rerendering),useRef passes in a parameter initValue and creates an object {current: InitValue} is used by the function component, and the object remains unchanged throughout its life cycle
      const Page = () = > {
        const leviRef = React.useRef(initialVal)
    
        const handleClick = useCallback(() = > {
          levi.current.focus();
        }, [])
    
        return <input ref={leviRef} onClick={handleClick} />
      },
    Copy the code
  • UseMemo and useCallback cache references or values to functions, useMemo cache data (all objects, including functions), and useCallback cache functions, both of which are common optimization strategies for Hooks, UseCallback (fn,deps) equivalent to useMemo(()=>fn,deps)
        const Page = () = > {
          const leviRef = React.useRef(initialVal)
          
          const handleClick = useCallback(() = > {
            levi.current.focus();
          }, [])
    
          return React.useMemo(() = <input ref={leviRef} onClick={handleClick} />,} []),Copy the code

16. What are the advantages of Hooks over HOC and Render Prop?

HOC is an API that promotes reuse logic to the top of a component, not to the parent, avoiding multiple levels of nesting

17, what optimizations are in hooks

  • The number of DEPS dependencies should not exceed three
  • Multiple related states, which are handled as objects. Otherwise, multiple states appear inside the hooks, which are difficult to maintain
  • SetState is used inside the useCallback, so consider using setState callback to reduce dependencies
      const useValues = () = > {
        const [values, setValues] = useState({});
    
        const updateData = useCallback((nextData) = > {
          setValues((prevValues) = > ({
            data: nextData,
            count: prevValues.count + 1,}));// Use the setState callback function to get the latest values state. The callback is no longer dependent on the external values variable, so no values need to be specified in the dependency array} []);// This callback will never be recreated
    
        return [values, updateData];
      };
    
    Copy the code
  • Can have ref to hold variables (ref will remain constant throughout the life of the component)

18. What is useCallback used for

Cache function

19, useEffect and useLayoutEffect difference?

UseEffect is a callback function that executes after render, but does not block the browser’s rendering. 2. The callback function in useLayoutEffect executes immediately after the DOM update is complete, but runs before the browser can do any drawing, blocking the browser’s drawing.

The React lifecycle getDrivedStatefromprops is static

React version 16.4 introduced, instead of for componentWillReceiveProps, when props or state changes, trigger, is a pure function. We can’t get this inside the function to prevent setState from creating an infinite loop.

Implement a custom hooks

Note: Custom hooks begin with use, or capitalize the function name (react will consider this a component). The react-hooks validation rule does not report errors

  // Get the current document title && Set the document title
  import { useState, useEffect, useCallback } from 'react';
  const useTitle = () = > {
    const [title, setTitle] = useState<string>(document.title);

    useEffect(() = > {
      document.title = title;
    }, [title]);

    const setDocumentTitle = useCallback(newTitle= >{ setTitle(newTitle); } []);return [title, setDocumentTitle];
  };

  export default useTitle;

  // fetch data
  import { useState, useCallback } from 'react';
  const useFetchCity = () = > {
    const [city, setCity] = useState<any[]>([]);
    const [loading, setLoading] = useState<boolean>(false);

    const getAllCity = useCallback(async () => {
      setLoading(true);

      const res = await new Promise(resolve= > {
        setTimeout(() = > {
          resolve([1.2.3.4]);
        }, 2000);
      });

      setCity(res);
      setLoading(false); } []);return [loading, city, getAllCity];
  };

  export default useFetchCity;


Copy the code