記一次react不正當操做state引起的bug

太長不看版 👉 直接跳到找到緣由javascript

bug復現

一個表單裏,用戶對以前填寫的數據進行修改,原始數據存在redux裏,用戶修改後會把redux裏的數據進行更新,當內容有修改時保存按鈕才能夠點擊,不然保存按鈕處於置灰狀態,數據是否有修改是經過componentWillReceiveProps新舊redux中的數據diff操做(用的lodash的isEqual),能夠說是很常見的場景了。可是呢,測試同窗卻一直反饋,保存按鈕在點擊以後仍然處於可點擊的狀態,很少說了,查bug了😑java

查找緣由

這裏不得不吐槽一下咱們出現問題的代碼文件十分的冗長,有2000多行,查找問題很是不便react

由於是按鈕狀態的問題,而按鈕的狀態又是經過新舊數據diff的,因此想到的第一個點確定就是數據問題,是否是數據傳給接口有問題,或者接口返回的數據有問題,排查了一下,數據沒問題,固然這也是意料之中。再看一下redux中的數據也是最新的數據。哎,繼續查唄😣git

既然數據都沒有問題,那麼就必然是diff的問題了,固然不能排除lodash的問題,可是做爲gitlab中40k+ star的庫仍是至關可靠的,實在查不出問題了再翻一下isEqual的源碼。由於咱們的diff操做是放在componentWillReceiveProps中,因此不可避免的打印了上次和此次的props的值,果真,問題出現了,componentWillReceiveProps中this.props和next.props的值是同樣的,想必形成此次bug的緣由確定在這了。可是呢,這就很奇怪,由於咱們都知道componentWillReceiveProps中this.props的值和next.props的值一般狀況下是不同的,那麼是什麼緣由形成的呢,帶着這樣的疑問,打開了react官網🤔redux

找到問題

一番查找後,我發現了這段話markdown

image.png

大體意思就是對於引用類型來講,當咱們修改裏面的內容時,儘管內容已經修改,可是仍是同一個實例,因此react無法判斷裏面的數據是否修改,因此,爲了不別的問題出現或者進行深比較,react會把props向下傳遞。gitlab

因此會不會是在咱們對錶單的數據進行處理時,修改了引用數據的內容,從而引起react觸發了componentWillReceiveProps,因此當redux保存新的數據時再觸發componentWillReceiveProps,此時this.props已經被更新了呢,這時再回頭看一下保存時的邏輯,果真裏面的代碼直接修改了state中的值而沒有經過setState。測試

錯誤代碼

import React from "react";
import { connect } from "react-redux";
import { illegalChangeState } from "../../actions/index";

class Test extends React.Component {
  constructor(...props) {
    super(...props);
    this.state = {
      obj: {
        a: 0,
      },
    };
  }
  componentWillReceiveProps(nextProps) {
    // 下面不正當操做state致使這裏this.props和nextProps的值是同樣的
    console.log(this.props);
    console.log(nextProps);
  }
  componentDidMount() {
    this.setState({
      obj: this.props.obj,
    });
  }
  changeState = () => {
    const { obj } = this.state;
    // 這裏直接修改了state
    obj.a = 2;
    this.props.illegalChangeState(obj.a);
  };

  render() {
    return <div onClick={this.changeState}>{this.state.obj.a}</div>;
  }
}

const mstp = (state) => {
  return {
    obj: state.obj,
  };
};

export default connect(mstp, { illegalChangeState })(Test);

複製代碼

知道了緣由以後,問題天然而然迎刃而解。ui

相關文章
相關標籤/搜索