美文网首页
实战升级react hooks

实战升级react hooks

作者: web_柚子小记 | 来源:发表于2019-11-20 17:27 被阅读0次

    getDerivedStateFromProps +componentDidUpdate 使用方法:

    import React from 'react';
    import { connect } from 'react-redux';
    import { Card, Table, Divider, Modal } from 'antd';
    import util from 'scripts/utils/util';
    import { operateType } from 'scripts/app/message';
    import service from 'scripts/services/auditService';
    import sty from '../audit.scss';
    
    class LogTable extends React.Component {
        state = {
            data: [],
            scopeType: this.props.scopeType, //🔴常见错误,props上scopeType的改变并不会触发state中scopeType的改变
            pagination: {
                current: 1,
                pageSize: 10
            },
            filterLogs: this.props.filterLogs,
        }
        componentDidMount() {
            this.searchList();
        }
        static getDerivedStateFromProps(props, state) {
            let data = {}
            if (state.scopeType !== props.scopeType) {
                data["scopeType"] = props.scopeType
            }
            if (JSON.stringify(state.filterLogs) !== JSON.stringify(props.filterLogs)) { //Todo 判断对象是否改变
                data["filterLogs"] = {
                    ...props.filterLogs
                }
            }
            return data;
        }
        componentDidUpdate(prevProps, prevState) {
            if (prevState.scopeType !== this.state.scopeType) {
                this.searchList();
            }
            if (JSON.stringify(prevProps.filterLogs) !== JSON.stringify(this.props.filterLogs)) {  //Todo 判断对象是否改变 
                this.searchList();
            }
        }
        searchList(current) {
            if (!this.state.filterLogs) return;
            const { filterLogs } = this.props;
            const { scopeType, pagination } = this.state;
            filterLogs.filterMap.scope = scopeType;
            let filters = {
                ...filterLogs,
                ...pagination,
                current: current || 1
            };
            
            service.searchLoglist(filters).then(res => {
                if (res.success) {
                    this.setState({ data: res.data });
                }
            });
            service.loadLoglist(filters).then(res => {
                if (res.success) {
                    this.setState({
                        pagination: {
                            ...this.state.pagination,
                            current: current || 1,
                            total: res.data
                        }
                    })
                }
            });
        }
        handleChange(pagination) {
            this.setState({
                pagination: {
                    ...this.state.pagination,
                    current: pagination.current
                }
            })
    
            this.searchList(pagination.current);
        }
        render() {
            const { data, scopeType, pagination } = this.state;
            const columns = [{
                title: '序号',
                key: 'id',
                render(data, record, index) {
                    return (pagination.current - 1) * 10 + index + 1;
                }
            }, {
                title: '操作时间',
                dataIndex: 'operatorTime',
                key: 'operatorTime',
                render(operatorTime) {
                    return new Date(operatorTime).format('yyyy-mmon-dd hh:mm');
                }
            }, {
                title: "客户端IP",
                dataIndex: 'ip',
                key: 'ip'
            }, {
                title: '用户昵称',
                dataIndex: 'operatorNickName',
                key: 'operatorNickName'
            }, {
                title: '用户邮箱',
                dataIndex: 'operatorEmail',
                key: 'operatorEmail',
                render(operatorEmail) {
                    return operatorEmail == 'null' ? '' : operatorEmail;
                }
            }, {
                title: '操作类型',
                key: 'operateType',
                render(record) {
                    return operateType[record.operateType];
                }
            }, {
                title: '操作对象',
                dataIndex: 'targetName',
                key: 'targetName',
                render(targetName) {
                    return util.msgType(targetName);
                }
            }, {
                title: '操作结果',
                dataIndex: 'result',
                key: 'result',
                render(result) {
                    return result === "SUCCESS" ? "成功" : "失败";
                }
            }]
    
            return (
                <div>
                    <Table
                        columns={columns}
                        rowKey={record => record.operatorTime}
                        dataSource={data}
                        pagination={pagination}
                        onChange={(pagination, filters, sorter) => this.handleChange(pagination, filters, sorter)}
                    />
                </div>
            );
        }
    }
    
    export default connect(
        state => {
            return {
                filterLogs: state.audit.filterLogs
            }
        }
    )(LogTable);
    
    image.png

    props属性:
    scopeType表示“用户日志”或“管理员日志”
    filterLogs表示过滤条件

    state属性:
    data表示表格的数据源
    pagination表示分页信息

    当props属性的scopeType和filterLogs发生变化时,需要调用searchList从而更新data和pagination

    然而,从上述代码中发现,当scopeType或filterLogs发生变化时,getDerivedStateFromProps和componentDidUpdate会分别执行三次。第一次是由于props属性的变化,而二、三次是由于在searchList中分别调用了两次setState方法,那么setState为什么会触发getDerivedStateFromProps呢?

    http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
    查阅到上面的生命周期表后,发现,^16.4以后,set­State和forceUpdate也会触发这个生命周期。因此state变化后,又会走 getDerivedStateFromProps 方法,并把 state 值更新为传入的 prop。

    react Hooks使用方法:

    import React, { useState, useEffect } from 'react';
    import { connect } from 'react-redux';
    import { Table } from 'antd';
    import util from 'scripts/utils/util';
    import { operateType } from 'scripts/app/message';
    import service from 'scripts/services/AuditService';
    
    function LogTable({ scopeType, filterLogs }) {
        const [data, setData] = useState([]);
        const [pagination, setPagination] = useState({ pageSize: 10 });
        const [current, setCurrent] = useState(1);
        const columns = [{
            title: '序号',
            key: 'id',
            render(data, record, index) {
                return (pagination.current - 1) * 10 + index + 1;
            }
        }, {
            title: '操作时间',
            dataIndex: 'operatorTime',
            key: 'operatorTime',
            render(operatorTime) {
                return new Date(operatorTime).format('yyyy-mmon-dd hh:mm');
            }
        }, {
            title: "客户端IP",
            dataIndex: 'ip',
            key: 'ip'
        }, {
            title: '用户昵称',
            dataIndex: 'operatorNickName',
            key: 'operatorNickName'
        }, {
            title: '用户邮箱',
            dataIndex: 'operatorEmail',
            key: 'operatorEmail',
            render(operatorEmail) {
                return operatorEmail == 'null' ? '' : operatorEmail;
            }
        }, {
            title: '操作类型',
            key: 'operateType',
            render(record) {
                return operateType[record.operateType];
            }
        }, {
            title: '操作对象',
            dataIndex: 'targetName',
            key: 'targetName',
            render(targetName) {
                return util.msgType(targetName);
            }
        }, {
            title: '操作结果',
            dataIndex: 'result',
            key: 'result',
            render(result) {
                return result === "SUCCESS" ? "成功" : "失败";
            }
        }];
    
        useEffect(() => {
            if (!filterLogs) return;
            filterLogs.filterMap.scope = scopeType;
            let filters = {
                ...filterLogs,
                ...pagination,
                current: current || 1
            };
    
            service.searchLoglist(filters).then(res => {
                if (res.success) {
                    setData(res.data);
                }
            });
            service.loadLoglist(filters).then(res => {
                if (res.success) {
                    setPagination({
                        ...pagination,
                        current: current || 1,
                        total: res.data
                    });
                }
            });
        }, [scopeType, filterLogs, current])
    
        function handleChange(pageInfo) {
            setCurrent(pageInfo.current)
        }
    
        return (
            <Table
                columns={columns}
                rowKey={record => record.operatorTime}
                dataSource={data}
                pagination={pagination}
                onChange={(pages) => handleChange(pages)}
            />
        );
    }
    
    export default connect(
        state => {
            return {
                filterLogs: state.audit.filterLogs
            }
        }
    )(LogTable);
    

    我不再需要去关心props属性的变化状态,不用去做各种判断去控制是否渲染。就像vue里面的computed计算属性,在react中使用useEffect,然后告诉它,帮我盯着scopeType, filterLogs, current这三个变量,只要发生变化,就立刻计算。
    同时,我也不需要去写N多this,就像阮大师说的:
    React 团队希望,组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。 组件的最佳写法应该是函数,而不是类。

    代码缩减了约50行,一气呵成
    惊艳!

    相关文章

      网友评论

          本文标题:实战升级react hooks

          本文链接:https://www.haomeiwen.com/subject/dganictx.html