component和render在react router中的应用

在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,可以避免组件复用,从而降低代码的复杂程度。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值