技术干货程序员

component和render在react router中的应

2019-04-04  本文已影响0人  大神带我来搬砖

在react router项目中,有这样的一个需求,首先展示用户名列表,点击某个用户名后,根据用户名在后台取得用户具体信息在详情页进行展示。

此时可以将详情页封装成一个组件,利用react router将userId传递给详情页组件,详情页组件向后台请求数据,然后进行展示。

component

使用component时,详情页组件代码如下

import {PureComponent, Component} from "react";
import React from "react";

class ComponentUser extends PureComponent {

    constructor(props) {
        super(props);
        this.state = {}
    }

    getUserId = () => {
        const {
            match: {
                params: {id},
            },
        } = this.props;
        return id;
    };

    fetchContent = (userId) => {
        console.log("fetch");
        this.setState({content: "loading"});
        new Promise(resolve => {
            setTimeout(() => {
                resolve("content of " + userId)
            }, 2000)
        }).then(content => {
            this.setState({content})
        })
    };

    componentDidMount() {
        const userId = this.getUserId();
        this.fetchContent(userId);
    }

    render() {
        const userId = this.getUserId();
        const {content} = this.state;

        return (
            <div>
                <div>{userId}</div>
                <div>{content}</div>
            </div>

        )
    }
}

export default ComponentUser

列表页代码如下

import React from "react";
import {BrowserRouter as Router, Route, Link} from "react-router-dom";
import RenderUser from './RenderUser'
import ComponentUser from './ComponentUser'

const App = () => (
    <Router>
        <div>
            <nav>
                <ul>
                    <li>
                        <Link to="/componentUser/user1">userA</Link>
                    </li>
                    <li>
                        <Link to="/componentUser/user2">userB</Link>
                    </li>
                </ul>
            </nav>

            <Route path="/componentUser/:id" component={ComponentUser}/>
        </div>
    </Router>
);

export default App;

不过此时会有个问题,切换点击切换userA和userB的时候,发现页面并没有更新,这是由component属性的性质决定的,react会进行组件复用。

所以需要在组件中添加componentDidUpdate函数,期望在userId发生变化后重新获取数据。

import {PureComponent, Component} from "react";
import React from "react";

class ComponentUser extends PureComponent {

    constructor(props) {
        super(props);
        this.state = {}
    }

    getUserId = () => {
        const {
            match: {
                params: {id},
            },
        } = this.props;
        return id;
    };

    fetchContent = (userId) => {
        console.log("fetch");
        this.setState({content: "loading"});
        new Promise(resolve => {
            setTimeout(() => {
                resolve("content of " + userId)
            }, 2000)
        }).then(content => {
            this.setState({content})
        })
    };

    componentDidMount() {
        const userId = this.getUserId();
        this.fetchContent(userId);
    }

    componentDidUpdate(prevProps) {
        const userId = this.getUserId();
        const {
            match: {
                params: {id: previousUserId},
            },
        } = prevProps;
        if (userId !== previousUserId) {
            this.fetchContent(userId);
        }
    }

    render() {
        const userId = this.getUserId();
        const {content} = this.state;

        return (
            <div>
                <div>{userId}</div>
                <div>{content}</div>
            </div>

        )
    }
}

export default ComponentUser

这里要注意的是,componentDidUpdate中需要判断当前的userId是否和原来的userId一致,只有不一致的时候才需要重新获取数据。不这样做的话,会导致无限循环的setState和componentDidUpdate。

render

使用render则可以减少三分之一的代码行数,此时详情页组件代码如下

import {PureComponent} from "react";
import React from "react";

class RenderUser extends PureComponent {

    constructor() {
        super();
        this.state = {}
    }

    componentDidMount() {
        console.log("fetch");
        this.setState({content: "loading"});
        const {userId} = this.props;
        new Promise(resolve => {
            setTimeout(() => {
                resolve("content of " + userId)
            }, 1000)
        }).then(content => {
            this.setState({content})
        })
    }


    render() {
        const {userId} = this.props;
        const {content} = this.state;

        return (
            <div>
                <div>{userId}</div>
                <div>{content}</div>
            </div>

        )
    }
}

export default RenderUser

列表页代码如下

import React from "react";
import {BrowserRouter as Router, Route, Link} from "react-router-dom";
import RenderUser from './RenderUser'
import ComponentUser from './ComponentUser'

const App = () => (
    <Router>
        <div>
            <nav>
                <ul>
                    <li>
                        <Link to="/renderUser/user1">user1</Link>
                    </li>
                    <li>
                        <Link to="/renderUser/user2">user2</Link>
                    </li>
                </ul>
            </nav>

            <Route path="/renderUser/:id" render={
                ({match}) => (<RenderUser key={match.params.id} userId={match.params.id}/>)
            }/>
        </div>
    </Router>
);

export default App;

可以看到由于将userId作为组件的key,可以避免组件复用,从而降低代码的复杂程度。

上一篇下一篇

猜你喜欢

热点阅读