道具改变后反应状态没有改变

时间:2021-03-22 08:24:11

标签: reactjs redux react-redux

我正在使用 redux 和 react,在我的 react 状态中,我正在为 props 分配一些状态属性,但在我的状态下,帐户正在更改但加载属性没有更改,我还尝试更新状态componentdidupdate 但是当我尝试这样做时,我超出了最大更新深度

在 AllAccounts 中,accounts 属性在帐户完成获取和道具更改时更新,但加载属性不会发生同样的情况,当它设置为 true 时,它​​被设置为第一个值,当它更改时, prop 值在加载时发生变化,但在状态中没有变化

这是我的组件

import React, { Component } from "react";
import { connect } from "react-redux";
import {
  getAccounts,
  deleteAccounts,
  addAccount,
} from "../../../actions/accountActions";
import { getUsersForTenant } from "../../../actions/userActions";

import { Drawer } from "antd";
import getSortUrl from "../../../utils/getSortUrl";
import "../tablepage.css";
import Table from "../../../components/Table/Table";
import SearchHeader from "../../../components/SearchHeader/SearchHeader";
import Loading from "../../../components/Loading/Loading";
import AddAccount from "../../../components/AddEntities/AddAccount/AddAccount";
class AllAccounts extends Component {
  constructor(props) {
    super(props);
    this.fetchData = this.fetchData.bind(this);
    this.setSort = this.setSort.bind(this);
    this.deleteRows = this.deleteRows.bind(this);
    this.toggleDrawer = this.toggleDrawer.bind(this);
    this.addAccount = this.addAccount.bind(this);
  }

  state = {
    page: 0,
    size: 50,
    loading: this.props.loading,
    accounts: this.props.accounts,
    sort: undefined,
    selectedItems: [],
    checkboxActive: false,
    drawerVisible: false,
    columns: [
      {
        key: "name",
        title: "Name",
        enabled: true,
        searchable: true,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: true,
      },
      {
        key: "companyDomain",
        title: "Company Domain",
        enabled: true,
        searchable: true,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "industrySector.name",
        title: "Industry Sector",
        enabled: true,
        searchable: true,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "picture",
        title: "Picture",
        enabled: false,
        searchable: false,
        type: "picture",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "nbrEmployees",
        title: "No. Employees",
        enabled: true,
        searchable: true,
        type: "number",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "fixedPhone",
        title: "Phone",
        enabled: true,
        searchable: true,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "source.name",
        title: "Source",
        enabled: false,
        searchable: true,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "linkedIn",
        title: "LinkedIn",
        enabled: true,
        searchable: false,
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "social",
        title: "Social Networks",
        title: "Social Networks",
        enabled: true,
        searchable: false,
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "twitterPage",
        title: "Twitter",
        title: "twitter",
        enabled: false,
        bindCol: "social",
        bindColTitle: "Social",
        searchable: false,
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "instagramPage",
        title: "Instagram",
        enabled: false,
        searchable: false,
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },

      {
        key: "googlePlus",
        title: "Google Plus",
        enabled: false,
        searchable: false,
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "user",
        title: "User",
        enabled: false,
        searchable: false,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "isCustomer",
        title: "Is Customer",
        enabled: false,
        searchable: false,
        type: "boolean",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
      {
        key: "Tags",
        title: "Tags",
        enabled: true,
        searchable: false,
        type: "string",
        selected: false,
        sortActive: false,
        sortOrder: "ASC",
        showCheckbox: false,
      },
    ],
  };

  toggleDrawer = () => {
    this.setState({
      drawerVisible: !this.state.drawerVisible,
    });
  };

  deleteRows = (rows) => {
    if (rows) {
      this.props.deleteAccounts(rows, 1);

      this.setState({
        loading: true,
      });
    } else {
      const { selectedItems } = this.state;

      this.props.deleteAccounts(selectedItems, 1);

      this.setState({
        selectedItems: [],
        loading: true,
      });
    }
  };

  addAccount = (accountData) => {
    this.props.addAccount(accountData, 1);
  };

  componentDidUpdate(prevState, prevProps, snap) {
    // if (prevProps.accounts != this.props.accounts) {
    //   this.setState({
    //     accounts: this.props.accounts,
    //     loading: false,
    //   });
    // }
    // if (prevProps.users != this.props.users) {
    //   this.setState({
    //     assignableUsers: this.props.users,
    //   });
    // }
  }

  setSort = (column) => {
    this.setState({
      sort: column,
    });
  };

  selectRow = (select, row) => {
    if (select) {
      this.setState({
        selectedItems: [...this.state.selectedItems, row],
        checkboxActive: true,
      });
    } else {
      var { selectedItems } = this.state;
      var index = 0;
      for (var i = 0; i < selectedItems.length; i++) {
        if (selectedItems[i].id == row.id) {
          console.log(i);
          index = i;
        }
      }
      selectedItems.splice(index, 1);

      if (selectedItems.length == 0) {
        this.setState({
          selectedItems: selectedItems,
          checkboxActive: false,
        });
      } else {
        this.setState({
          selectedItems: selectedItems,
        });
      }
    }
  };

  fetchData = () => {
    this.setState(
      {
        loading: true,
      },
      () => {
        const { page, size, sort } = this.state;
        var sortUrl = "";
        if (sort) {
          const sortKey = sort.key;
          const sortOrder = sort.sortOrder;

          sortUrl = getSortUrl(sortKey, sortOrder);
        }

        this.props.getAccounts(page, size, sortUrl);
      }
    );
  };

  componentDidMount() {
    this.fetchData(0, 50, undefined);
    this.props.getUsersForTenant();
  }

  toggleEnableColumn = (index) => {
    const { columns } = this.state;
    var enableOccured = false;

    columns[index].enabled = !columns[index].enabled;
    columns.forEach((col) => {
      if (!enableOccured && col.enabled) {
        col.showCheckbox = true;
        enableOccured = true;
      } else {
        col.showCheckbox = false;
      }
    });

    this.setState({
      columns: columns,
    });
  };

  render() {
    const {
      size,
      page,
      accounts,
      columns,
      loading,
      checkboxActive,
      drawerVisible,
    } = this.state;

    return (
      <div className="table-page-container">
        <Loading loading={loading} />
        <Drawer
          title="Add New Account"
          placement="right"
          closable={true}
          visible={drawerVisible}
          onClose={this.toggleDrawer}
        >
          <AddAccount
            toggleDrawer={this.toggleDrawer}
            assignableUsers={this.props.users}
            addAccount={this.addAccount}
          />
        </Drawer>
        <div className="breadcrumb-container"></div>
        <div className="searchbar-container">
          <SearchHeader
            columns={columns}
            checkboxActive={checkboxActive}
            fetchData={this.fetchData}
            deleteData={this.deleteRows}
            toggleDrawer={this.toggleDrawer}
          />
        </div>
        <Table
          size={size}
          page={page}
          data={accounts}
          checkboxActive={checkboxActive}
          module={"accounts"}
          columns={columns}
          toggleEnableColumn={this.toggleEnableColumn}
          className="table-container"
          selectRow={this.selectRow}
          fetchData={this.fetchData}
          setSort={this.setSort}
          deleteData={this.deleteRows}
        />
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    accounts: state.account.accounts,
    users: state.user.users,
    loading: state.account.loading,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    getAccounts: (page, size, sort) => dispatch(getAccounts(page, size, sort)),
    addAccount: (accountData, accountType) =>
      dispatch(addAccount(accountData, accountType)),

    deleteAccounts: (rows, accountType) =>
      dispatch(deleteAccounts(rows, accountType)),
    getUsersForTenant: () => dispatch(getUsersForTenant()),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(AllAccounts);

这是减速机

import {
  GET_ACCOUNT,
  GET_ACCOUNTS,
  GET_CUSTOMERS,
  GET_PROSPECTS,
  DELETE_ACCOUNT,
  SET_ACCOUNTS_LOADING,
  SET_ACCOUNTS_ERROR,
  CLEAR_ERRORS,
} from "../actions/types";

const defaultState = {
  accounts: [],
  customers: [],
  prospects: [],
  loading: false,
  errors: {},
};

const accountReducer = (state = defaultState, action) => {
  switch (action.type) {
    case GET_ACCOUNTS:
      return {
        ...state,
        accounts: action.payload,
        errors: {},
      };
    case GET_CUSTOMERS:
      return {
        ...state,
        customers: action.payload,
        errors: {},
      };
    case GET_PROSPECTS:
      return {
        ...state,
        prospects: action.payload,
        errors: {},
      };
    case CLEAR_ERRORS:
      return {
        ...state,
        errors: {},
      };
    case SET_ACCOUNTS_LOADING:
      return {
        ...state,
        loading: action.payload,
      };
    case SET_ACCOUNTS_ERROR:
      return {
        ...state,
        errors: action.payload,
      };
    default:
      return state;
  }
};

export default accountReducer;

1 个答案:

答案 0 :(得分:2)

您可能需要的是 static getDerivedStateFromProps(props, state)

<块引用>

此方法适用于状态取决于道具随时间变化的罕见用例。

为了让 props 流经本地状态,您可以在该生命周期方法中编写逻辑。

 static getDerivedStateFromProps(props, state) {
    if (!isEqual(props.accounts,state.accounts)) {
      return {
        accounts: props.accounts
      };
    }
    return null;
  }
}

请注意,我使用 isEqual 中的 lodash/isEqual 来深入检查 state 和 props 之间的相等性,否则它会在每次 props 流入时更新。

参考:https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops