Use of component and render attributes in Route of React router

In the component part of the official document of the react router , it says:

When you use component (instead of render or children, below) the router uses React.createElement to create a new React element from the given component. That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component. When using an inline function for inline rendering, use the render or the children prop (below).

How to understand this passage? This can be illustrated by a small example.

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route} from "react-router-dom";

class Bar extends React.Component {

    componentDidMount() {
        console.log("componentDidMount")
    }

    render() {
        return (
            <div>Bar</div>
        )
    }
}

class App extends React.Component {

    builder (prop) {
        super(prop);
        this.state = {idx: 1}
    }

    handleClick = () => {
        this.setState(state => ({idx: state.idx + 1}))
    };

    render() {
        return (
            <div>
                <div>
                    {this.state.idx}
                    <button onClick={this.handleClick}>add</button>
                </div>
                <div>
                    <BrowserRouter>
                        <Route component={Bar}/>
                    </BrowserRouter>
                </div>
            </div>
        );
    }
}


ReactDOM.render(<App/>, document.getElementById('root'));

 

In the above code, there is a simple Bar component in the App component, which is referenced by Route through the component attribute.

<Route component={Bar}/>

 

At this time, click the button on the page, the componentDidMount of the Bar component will not be triggered.
Suppose now that you need to accept the idx in the App in the Bar component, you need to pass the idx as props to Bar, at this time you can write the following code

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route} from "react-router-dom";

class Bar extends React.Component {

    componentDidMount() {
        console.log("componentDidMount")
    }

    render() {
        const {idx} = this.props;
        return (
            <div>in Bar : {idx}</div>
        )
    }
}

class App extends React.Component {

    builder (prop) {
        super(prop);
        this.state = {idx: 1}
    }

    handleClick = () => {
        this.setState(state => ({idx: state.idx + 1}))
    };

    render() {
        return (
            <div>
                <div>
                    {this.state.idx}
                    <button onClick={this.handleClick}>add</button>
                </div>
                <div>
                    <BrowserRouter>
                        <Route component={() => (<Bar idx={this.state.idx}/>)}/>
                    </BrowserRouter>
                </div>
            </div>
        );
    }
}


ReactDOM.render(<App/>, document.getElementById('root'));

 

However, at this time, click the button and find that Bar's componentDidMount has been called, just like the above document says

That means if you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component.

So the correct wording should be

<Route render={() => (<Bar idx={this.state.idx}/>)}/>

 

At this time, the Bar component will not have repeated unmounting and mounting.

The principle behind it is that when react compares the state of the component to decide how to update the dom node, it must first compare the type and key of the component. In use <Route component={() => (<Bar idx={this.state.idx}/>)}/>, because of the call React.createElement, the type of the component is not Bar, but an anonymous function. The App component generates a new anonymous function each time it is rendered, resulting in the type of the generated component always being different, so repeated unmounting and mounting will occur.

Reference documentation:
https://reactjs.org/docs/reconciliation.html
https://reactjs.org/docs/react-api.html#createelement



Author: Great God brought me to move bricks
link: https: //www.jianshu.com/p/a2a9b469a422
Source: Jane books
are copyrighted by the author. For commercial reproduction, please contact the author for authorization, and for non-commercial reproduction, please indicate the source.

Guess you like

Origin www.cnblogs.com/cangqinglang/p/12742159.html