實戰(zhàn)升級react hooks

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的改變并不會觸發(fā)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: '操作結(jié)果',
            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表示表格的數(shù)據(jù)源
pagination表示分頁信息

當props屬性的scopeType和filterLogs發(fā)生變化時涡拘,需要調(diào)用searchList從而更新data和pagination

然而,從上述代碼中發(fā)現(xiàn)模聋,當scopeType或filterLogs發(fā)生變化時,getDerivedStateFromProps和componentDidUpdate會分別執(zhí)行三次唠亚。第一次是由于props屬性的變化链方,而二、三次是由于在searchList中分別調(diào)用了兩次setState方法灶搜,那么setState為什么會觸發(fā)getDerivedStateFromProps呢祟蚀?

http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
查閱到上面的生命周期表后,發(fā)現(xiàn)割卖,^16.4以后前酿,set-State和forceUpdate也會觸發(fā)這個生命周期。因此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: '操作結(jié)果',
        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);

我不再需要去關(guān)心props屬性的變化狀態(tài)丙挽,不用去做各種判斷去控制是否渲染肺孵。就像vue里面的computed計算屬性,在react中使用useEffect颜阐,然后告訴它平窘,幫我盯著scopeType, filterLogs, current這三個變量,只要發(fā)生變化凳怨,就立刻計算瑰艘。
同時,我也不需要去寫N多this,就像阮大師說的:
React 團隊希望磅叛,組件不要變成復雜的容器屑咳,最好只是數(shù)據(jù)流的管道。開發(fā)者根據(jù)需要弊琴,組合管道即可兆龙。 組件的最佳寫法應(yīng)該是函數(shù),而不是類敲董。

代碼縮減了約50行紫皇,一氣呵成
驚艷!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腋寨,一起剝皮案震驚了整個濱河市聪铺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌萄窜,老刑警劉巖铃剔,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異查刻,居然都是意外死亡键兜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門穗泵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來普气,“玉大人,你說我怎么就攤上這事佃延∠志鳎” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵履肃,是天一觀的道長仔沿。 經(jīng)常有香客問我,道長尺棋,這世上最難降的妖魔是什么封锉? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮陡鹃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抖坪。我一直安慰自己萍鲸,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布擦俐。 她就那樣靜靜地躺著脊阴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘿期,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天品擎,我揣著相機與錄音,去河邊找鬼备徐。 笑死萄传,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蜜猾。 我是一名探鬼主播秀菱,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蹭睡!你這毒婦竟也來了衍菱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤肩豁,失蹤者是張志新(化名)和其女友劉穎脊串,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體清钥,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡琼锋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了循捺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斩例。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖从橘,靈堂內(nèi)的尸體忽然破棺而出念赶,到底是詐尸還是另有隱情,我是刑警寧澤恰力,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布叉谜,位于F島的核電站,受9級特大地震影響踩萎,放射性物質(zhì)發(fā)生泄漏停局。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一香府、第九天 我趴在偏房一處隱蔽的房頂上張望董栽。 院中可真熱鬧,春花似錦企孩、人聲如沸锭碳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽擒抛。三九已至推汽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歧沪,已是汗流浹背歹撒。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诊胞,地道東北人暖夭。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像厢钧,于是被迫代替她去往敵國和親鳞尔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361