Recently, the team is recruiting, so I have prepared some basic interview questions. If you are interested, please leave a message and I will update it

As an advertisement, ele. me’s business ordering front team continues to recruit interested individuals

What are the ways React creates components? What’s the difference?

React builds components in three ways

  • React.createClass
  • ES6 class
  • Stateless function

React. CreateClass is the most traditional and compatible method of React. This method builds a component object, and when the component is called, several instances of the component are created

The ES6 class approach is similar to createClass, but instead of calling internal methods, it uses classes.

Stateless components are always created with an instance, avoiding unnecessary checks and memory allocation.

What is the React lifecycle? What does each life cycle do?

The React lifecycle consists of MOUNTING, RECEIVE_PROPS, and UNMOUNTING

  • Component mount time (initialization of component state, reading initial state and props and two lifecycle methods, run only once at initialization time)
    • ComponentWillMount is called before Render (setState is called before Render). Therefore, this.state is not the latest, so the updated this.state can be obtained in render.
    • ComponentDidMount is called after Render
  • Component update (a component update is a set of updated actions that occur when the parent passes down props or when the component itself executes the setState method)
    • State updates for the components themselves, in sequence
      • ShouldComponentUpdate (shouldComponentUpdate (should accept props and state that need to be updated, let the developer add the necessary criteria, update when it needs to, and not update when it doesn’t need to. If false is returned, the component no longer executes the lifecycle method downward.
      • componentWillUpdate
      • Render (get the latest this.state)
      • ComponentDidUpdate (can get the latest this.state)
    • The parent component updates props while updating
      • ComponentWillReceiveProps (in this call setState, will not trigger a re – render, but will be carried out in the consolidation of the state. Therefore, this.state is not the latest, and the updated this.state can be obtained in render.
      • shouldComponentUpdate
      • componentWillUpdate
      • render
      • componentDidUpdate
  • Component uninstallation
    • ComponentWillMount (We often perform some cleanup methods during component uninstallation, such as event collection, empty timer)

The new version of the lifecycle function adds getDerivedStateFromProps, which essentially maps the passed props to state. After React 16.4, this function is called every time before re-render,

The function of getDerivedStateFromProps is

  • Update internal state unconditionally based on prop, i.e. update state whenever a prop value is passed in
  • The state value is updated only when the prop value and state value are different.

But blindly using this lifecycle can be problematic

  • Copy props directly to state
  • Update state if the props and state are inconsistent

In what life cycle is DOM actually added to HTML?

ComponentDidMount, componentDidUpdate

What happened after the state update

After the state update, shouldComponentUpdate, componentWillUpdate, Render, and componentDidMount are executed in order. ShouldComponentUpdate accepts props and state that needs to be updated, allowing the developer to add the necessary criteria and update it when it needs to and not update it when it doesn’t. If false is returned, the component no longer executes the lifecycle method downward.

Is setState really asynchronous

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() 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 second parameter setState(partialState, callback) can be used to get the updated result.

SetState is “asynchronous” only in synthetic events and hooks (), and synchronous in both native events and setTimeout.

What happens after setState

React uses the state queue mechanism to update setState asynchronously, avoiding frequent repeated updates to the state.

The new state is first merged into the status update queue, and then the component needs to be updated based on the status of the update queue and shouldComponentUpdate.

Complex version:

  1. EnqueueSetState queues the state and calls enqueueUpdate to process the Component to update
  2. If the Component is currently in an Update transaction, store the Component in the dirtyComponent first. Otherwise, the batchedUpdates handler is called.
  3. BatchedUpdates initiates a transaction.perform() transaction
  4. Transaction initialization starts, runs, and finishes
    1. Initialization: There are no methods registered during transaction initialization, so there are no methods to execute
    2. Run: Callback method passed in when setSate is executed
    3. The end: Update isBatchingUpdates to false and execute the close method in the wrapper for FLUSH_BATCHED_UPDATES. It loops through all the dirtyComponents, calls updateComponent to refresh the component, and executes its pendingCallbacks, the callback set in setState.

What happens when you use setState in shouldComponentUpdate or componentWillUpdate?

When setState is called, the new state is actually merged into the status update queue and the partialState and _pendingStateQueue update queues are merged. The state update is finally performed through enqueueUpdate.

If setState is used in shouldComponentUpdate or componentWillUpdate, the state queue (_pendingStateQueue) is not null. The updateComponent method is called, and the updateComponent method continues to call shouldComponentUpdate and componentWillUpdate, causing an infinite loop.

Why can’t you just use this.state to change data

SetState implements state updates through a queue mechanism. When setState is executed, the state that needs to be updated is merged into the status queue instead of updating this.state immediately. The queue mechanism can efficiently update state in batches. If this. State is directly modified without setState, the state will not be put into the state queue, and the state directly modified before will be ignored when setState is called next time and the state queue is merged. And cause unpredictable errors.

How to optimize stateless components without shouldComponentUpdate method?

Because stateless components have no life cycle, there is no shouldComponentUpdate. ShouldComponentUpdate is designed to avoid unwanted re-rendering.

So stateless components are rerendered every time. Some components have some unnecessary wear and tear on performance. We can refer to the Pure method of the Recompose library. (The Pure method actually converts stateless components into components with class syntax added to PureRender.)

What does setState do after that, when should you use setState, execute setState in componentWillMount, componentDidMount

React DOM

How do I insert a component directly under the body

With Protal, portal sets up a “portal” so that a component like Dialog is no different from any other component in the presentation layer, but the rendered object appears in another place as if it had passed through the portal.

Before v16 version, is to use unstable_renderSubtreeIntoContainer this API. If you have unstable in the name, this is an API that is discouraged but necessary to solve the problem. This API is similar to Render in that it updates the component to the DOM node passed in, and allows you to implement cross-component DOM operations within the component.

We can see in the source code, unstable_renderSubtreeIntoContainer method and the difference between a render method is unstable_renderSubtreeIntoContainer will pass in a parent node, Render The parameter is null.

After v16, you can use the createPortal method with render.

render() {
    return createPortal(
      <div class="dialog">
        {this.props.children}
      </div>.// JSX inserted into the portal
      this.node // DOM node on the other side of the portal
    );
  }
Copy the code

What does a ref do in React?

Obtain using refs. Component is invoked to create a new instance of the widget. The refs points to the instance, which can be a callback function that executes immediately after the component is mounted.

If we put refs in the input of the native DOM component, we can get DOM nodes from refs. If we put refs in the React component, we get the instance of the component, so we can call the instance’s methods. (If we want to access the real DOM of the component, we can use React.findDOMNode to find the DOM node, but this method is not recommended.)

Refs cannot be used for stateless components, which are mounted only as method calls without creating new instances. After V16, useRef can be used.

How to implement the React virtual DOM

React converts a real DOM tree into a JS object tree, also known as a Virtual DOM. After each data update, the VM is recalculated and compared with the VM tree generated last time, and the changed part is updated in batches. In addition to performance, the biggest benefit of VM implementation is integration with other platforms.

Let’s say we have a real DOM that looks like this

<button class="myButton">
  <span>this is button</span>
</button>
Copy the code

So this is what it looks like after it’s converted to VM

{
  type: 'button',
  props: {
  	className: 'myButton',
    children: [{
      type: 'span',
      props: {
        type: 'text'
        children: 'this is button'
      }
    }]
  }
}
  
Copy the code

Why does VM improve performance?

Because the VM does not actually manipulate the DOM, the diff algorithm improves performance by avoiding some of the invariant DOM operations.

Does VM necessarily improve performance?

Not necessarily, because the VM just avoids some DOM operations that don’t need to be changed through diff algorithms, which ultimately have to be done with the DOM, and diff comes at a cost.

For some scenarios, such as operations that require DOM changes, the VM approach does not improve performance or is even slower than the native DOM because of the additional diff algorithm costs involved.

But as Yudhoyono says, it’s a performance vs. maintainability trade-off. The point of a framework is to mask the underlying DOM manipulation for you and make your code more maintainable by allowing you to describe your purpose in a more declarative way. No framework can be faster than purely manual DOM optimization, because the framework’s DOM manipulation layer needs to handle any operations that the upper API might produce, and its implementation must be universal. I can write manual optimizations faster than any framework for any benchmark, but what’s the point? When building a real application, do you manually optimize everything? This is obviously not possible for maintainability reasons. The framework gives you the assurance that you don’t need to

Just a quick introduction to the Diff algorithm

The DIff algorithm has three main strategies (observed rules)

  • The movement of DOM nodes across hierarchies is minimal and can be ignored
  • Two components with the same class will generate similar tree structures, and two components with different classes will generate different tree structures
  • A set of child nodes at the same level can be distinguished by unique ids

tree diff

Because of the first of the three strategies, there are fewer cross-level operations on DOM nodes, the DIff algorithm will only compare DOM nodes at the same level. If it is found that the node does not exist, the node and its children are removed completely and the comparison is not continued. If a DOM node is moved across hierarchies, the node and all of its children are removed and then recreated in its place.

component diff

If it is a component of the same type, then the number of VMS will continue to be compared. If it is not a component of the same type, then it will be completely replaced with its children and will not be compared with components of the same type. It is possible that the VM has not changed at all, and if you know this for sure, you can save a lot of diff time. So the user can set shouldComponentUpdate() to determine if the diff algorithm is needed.

element diff

When a node is at the same level, there are three operations: INSERT_MAKEUP insert, MOVE_EXISTING move, and REMOVE_NODE delete. React is an optimization strategy that adds a unique key to a group of children at the same level. In this case, you can determine if it is a moving node. Using the key to find that the nodes in the old and new collections are the same node, you just need to move them. Of course, the optimization strategy and the specific diff method are very complicated, so I won’t expand it.

The react – in the router<Link>The labels and<a>What’s the difference in labels

By comparing tags, Link avoids unnecessary rerendering

React – Router is a routing system developed along with the React framework. It is also recognized as an excellent routing solution. When using the React-Router, we often use its own path redirect component Link to realize the redirect.

The React-Router takes over its default Link jump behavior. Unlike traditional page hops, Link’s “jump” behavior only triggers the corresponding page content update, but does not refresh the entire page.

Link jump does three things:

  1. If you have onclick, do onclick
  2. Prevent a tag from default event when click
  3. Use history to jump from the jump href, only the link has changed, but the page has not been refreshed

The A tag is a normal hyperlink, used to jump from the current page to another page (not the anchor point).

React event system

React event agent mechanism

React does not bind all handlers directly to real nodes. Instead, all events are bound to the outermost layer of the structure, using a unified event listener that maintains a map to hold event listeners and handlers within all components.

When a component is mounted or unmounted, objects are simply inserted or removed from this unified event listener.

When an event occurs, it is first handled by the unified event listener, and then the actual event handler is found in the map and called.

This has the advantage of resolving compatibility issues and simplifying event handling and recycling mechanisms (there is no need for manual unbinding events; React already handles them internally). However, some React events are not implemented, such as the Window resize event.

How does React’s event broker differ from its native event binding?

  1. Event propagation and preventing event propagation: React’s composite event does not implement event capture, only event bubbling. React prevents events from propagatinge.preventDefault()Native compatibility issues exist.
  2. Event types: React is a subset of the native event types. (React only implements the DOM Level3 event interface. Some events React does not implement, such as the Window resize event.) Preventing React events from bubbling can only be used in the React synthetic event system, but preventing React synthetic events from propagating in the React native event system.
  3. Event binding: There are several ways to bind events in the native event system. React supports only one way
  4. Event objects: There are compatibility issues with native IE. React is compatible.

What’s wrong with React’s event broker and native event binding?

We should avoid mixing React’s event broker mechanism with native event binding as much as possible.

React’s composite event layer does not bind events directly to DOM elements, so using e.topPropagation () to prevent native DOM bubblings will not work. Preventing React events from bubbling can only be used in the React synthetic event system, but preventing React synthetic events from propagating in the React native event system.

What happens if anonymous functions are used for binding events in React

class Demo {
  render() {
    return <button onClick={(e)= >{alert(' I clicked the button ')}}> button</button>}}Copy the code

In this way, because anonymous functions are used, the component is treated as a new props each time, and no cache optimization is used, resulting in a performance loss.

React Component communication

  • Parent component communicates to child component: props
  • Child component to parent component communication: callback function
  • Cross-level component communication: Context
  • Component communication without nested relationships: eventEmitter uses global objects to store events and broadcast events.

Performance optimization

What performance optimizations can be made in React?

  • ShouldComponentUpdate is used to avoid unnecessary rendering, but it is expensive to make deep comparisons between props and state, so some trade-offs need to be made depending on the business; In the case of a child component, to avoid repeated rendering of the child component, the parent component can determine whether the child component needs a PureRender.
  • Set the props to arrays or objects: each call to the React component creates a new component, even if the value of the array or object passed in does not change, their reference address will change. For example, if we write the following, then the style will be a new object every time we render
/ / do not recommend
<button style={{ color: 'red'}} / >/ / recommend
const style = { color: 'red' }
<button style={style} />

/ / do not recommend
<button style={this.props.style| | {}} / >  

/ / recommend
const defaultStyle = {}
<button style={this.props.style || defaultStyle } />   
Copy the code
  • Move the binding of a function into the constructor: you can avoid binding events every time.
  • Use immutable data. When using reference types in our project, shallowCopy and deepCopy are generally recommended to process data in order to avoid affecting the original data. However, this can cause a waste of CPU and memory. Therefore, immutable is recommended. It has the following advantages
    • Reduced “mutable” complexity
    • Memory saving, immutable uses structure sharing to reuse as much memory as possible, unreferenced objects are garbage collected
    • Can do undo/redo, copy/paste, time travel better
    • There is no concurrency problem (because the data itself is immutable)
    • Embrace functional programming
  • Give the child components a unique key, because in the diff algorithm, a key is used as a unique identifier to optimize rendering

Why is a component key set

During development, we need to ensure that an element’s key is unique among its siblings. In the React Diff algorithm, React uses the Key value of an element to determine whether it is a newly created or moved element, thus reducing unnecessary element re-rendering. React also uses Key values to determine the relationship between elements and local state.

HOOKS

React hooks, which bring those conveniences

React state, various lifecycle hook class components cannot be used in function-defined components before hooks. After React 16.8, a new feature was introduced: Hooks, which allow us to use class component features in function-defined components. Benefits:

  1. Reusing across components: Compared to render props/HOC, Hooks are the lightest, cheaper, low-level APIS that do not impact the original component hierarchy and the legendary nested hell;
  2. Class definitions are more complex
  • Different life cycles can make logic decentralized and confusing, difficult to maintain and manage;
  • Always pay attention to the direction of this;
  • The cost of code reuse is high, and the use of higher-order components often makes the whole component tree become bloated.
  1. State and UI isolation: Because of the Hooks nature, state logic is reduced to smaller granularity and easily abstracts into a custom Hooks, making state and UI in components clearer and more isolated.

Note:

  • Avoid using hooks in loop/conditional/nested functions to keep the order of calls stable.
  • Do not use useState in useEffect. React generates an error message.
  • Class components cannot be replaced or discarded, and there is no need to force class components to be modified. Both methods can coexist

Name a few common hooks

  • State hook (useState): Used to define the State of a component, similar to the functionality of this. State in class definitions
  • Lifecycle hooks (useEffect): There are many lifecycle functions in the class definition, and a corresponding function (useEffect) is provided in React Hooks, ComponentDidMount, componentDidUpdate and componentWillUnmount.
  • useContext: Gets the context object
  • useCallback: Cache the callback function, avoid the incoming callback is a new function instance each time and cause the dependent component to render again, with the effect of performance optimization;
  • useMemo: used to cache the incoming props so that dependent components are not re-rendered each time;
  • useRef: Gets the real node of the component;

How do use effects in React Hooks distinguish between lifecycle Hooks

UseEffect can be seen as > componentDidMount, > componentDidUpdate and > componentWillUnmount. UseEffect (callback, [source]) takes two arguments and is called as follows

useEffect(() => {
   console.log('mounted');
   
   return () => {
       console.log('willUnmount');
   }
 }, [source]);
Copy the code

** Lifecycle function calls are mainly controlled by the second parameter [source], in the following cases:

  • [source]If no parameter is passed, the function returned from the last saved function will be called first each time, and then the external function will be called.
  • [source]When [] is passed, the external function is called only once during initialization, and the returned function is called only once when the component is unloaded.
  • [source]If the parameter has a value, the returned function will be called first when the value in the array changes, and then the external function will be called.

Connect the principle

Connect is essentially a HOC layer that is wrapped on top of the original application component so that the child component of the original application as a Provider receives the Store of Redux as props and passes it to the Connect on the descendant component through the context object

Take mapStateToProps, mapDispatchToProps, return a function that produces Component (wrapWithConnect), and pass the real Component as an argument to wrapWithConnect. This produces a wrapped Connect component,

Fiber?

React Fiber is a re-implementation of the core algorithm ** As applications get bigger and bigger, the entire rendering process becomes more and more demanding. The large number of component renderings can cause the main process to be tied up for long periods of time, resulting in stutter and frame drops in some animations or high-frequency operations. The key is synchronous blocking. In previous scheduling algorithms, React needed to instantiate each class component, generate a tree of components, and traverse rendering in a synchronous recursive manner. The biggest problem with this process was that it could not be paused and resumed.

  • inReact V16The scheduling algorithm has been reconstructed, and the previousstack reconcilerReconstitute the new version of Fiberreconciler, became a single list tree traversal algorithm with linked lists and Pointers. With pointer mapping, each cell records the last and next steps traversed at the moment, making traversal pause and restart possible
  • Here I understand it as a task segmentation scheduling algorithm, which mainly divides the original synchronous update and rendering tasks into independent small task units, disperses the small tasks to the idle time of the browser according to different priorities, and makes full use of the event cycle mechanism of the main process