【问题标题】:Redux dispatch not properly updating stateRedux dispatch 没有正确更新状态
【发布时间】:2019-05-15 23:27:34
【问题描述】:

我的 Redux reducer 无法正确更新状态时遇到问题。

这是我在accountActions.js 文件中的操作。

// Get all accounts for specific user
export const getAccounts = () => dispatch => {
  dispatch(setAccountsLoading); // NOT WORKING
  axios
    .get("/api/plaid/accounts")
    .then(res =>
      dispatch({
        type: GET_ACCOUNTS,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: GET_ACCOUNTS,
        payload: null
      })
    );
};

// Accounts loading
export const setAccountsLoading = () => {
  return {
    type: ACCOUNTS_LOADING
  };
};

这是我的actionsReducers.js 文件。

import {
  GET_ACCOUNTS,
  ACCOUNTS_LOADING,
} from "../actions/types";

const initialState = {
  accounts: [],
  loading: false
};

export default function(state = initialState, action) {
  switch (action.type) {
    case ACCOUNTS_LOADING:
      return {
        ...state,
        loading: true
      };
    case GET_ACCOUNTS:
      return {
        ...state,
        accounts: action.payload,
        loading: false
      };
    default:
      return state;
  }
}

getAccounts 操作中的 dispatch(setAccountsLoading) 未正确更新 loading 状态。

在我的Dashboard.js 组件中,我调用getAccounts。基于loading 状态,我希望显示“正在加载...”消息。如果从getAccounts 返回的帐户为零,我希望显示一条消息以添加第一个帐户。否则,如果getAccounts 返回多个帐户,我希望显示仪表板。

这是我的Dashboard.js 组件。

import React, { Component } from "react";
import PlaidLink from "react-plaid-link";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { logoutUser } from "../../actions/authActions";
import {
  getAccounts,
  addAccount
} from "../../actions/accountActions";

import Transactions from "./Transactions";

class Dashboard extends Component {
  componentDidMount() {
    this.props.getAccounts();
  }

  // Logout
  onLogoutClick = e => {
    e.preventDefault();
    this.props.logoutUser();
  };

  // Add account
  handleOnSuccess = (token, metadata) => {
    const plaidData = {
      public_token: token,
      metadata: metadata
    };

    this.props.addAccount(plaidData);
  };

  render() {
    const { accounts, loading } = this.props.plaid;

    let dashboardContent;

    // Loading state is always false (setAccountsLoading not being called properly)
    if (loading) {
      dashboardContent = <p>Loading...</p>;
    } else if (accounts === null || Object.keys(accounts).length === 0) {
      dashboardContent = (
        <div>
          <h4>
            <b>Welcome,</b> User
          </h4>
          <p className="flow-text grey-text text-darken-1">
            To get started, link your first bank account below
          </p>
          <PlaidLink
            clientName="Mosaic"
            className="btn btn-large waves-effect waves-light hoverable blue accent-3"
            env="sandbox"
            product={["auth", "transactions"]}
            publicKey="0c3ff69a2efea552189de8b7fbbc0f"
            onSuccess={this.handleOnSuccess}
            style={{
              width: "185px",
              letterSpacing: "1.5px",
              borderRadius: "3px",
              marginTop: "1rem"
            }}
          >
            Link Account
          </PlaidLink>
          <button
            style={{
              width: "185px",
              borderRadius: "3px",
              letterSpacing: "1.5px",
              marginTop: "1rem"
            }}
            onClick={this.onLogoutClick}
            className="btn btn-large waves-effect waves-light hoverable red accent-3"
          >
            Logout
          </button>
        </div>
      );
    } else {
      dashboardContent = <Transactions accounts={accounts} />;
    }

    return (
      <div className="container">
        <div className="row">
          <div className="col s12 center-align">{dashboardContent}</div>
        </div>
      </div>
    );
  }
}

Dashboard.propTypes = {
  logoutUser: PropTypes.func.isRequired,
  getAccounts: PropTypes.func.isRequired,
  addAccount: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  plaid: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  plaid: state.plaid
});

export default connect(
  mapStateToProps,
  { logoutUser, getAccounts, addAccount }
)(Dashboard);

加载值始终为 false(在任何时候都不会切换为 true)。在我的仪表板中,如果我console.log(loading),我会看到两条消息显示loading 为假(一条在getAccounts 被触发时,一条在getAccounts 完成时)。

我目前使用的一种(不正确的)解决方法是从我的组件本身调用setAccountsLoading。当我这样做时,加载值将设置为 true,直到 getAccounts 完成(将 loading 设置回 false)。

import React, { Component } from "react";
import PlaidLink from "react-plaid-link";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { logoutUser } from "../../actions/authActions";
import {
  getAccounts,
  setAccountsLoading,
  addAccount
} from "../../actions/accountActions";

import Transactions from "./Transactions";

class Dashboard extends Component {
  componentDidMount() {
    this.props.getAccounts();
    // Temporary workaround; this has the desired outcome
    this.props.setAccountsLoading();
  }

  // Logout
  onLogoutClick = e => {
    e.preventDefault();
    this.props.logoutUser();
  };

  // Add account
  handleOnSuccess = (token, metadata) => {
    const plaidData = {
      public_token: token,
      metadata: metadata
    };

    this.props.addAccount(plaidData);
  };

  render() {
    const { accounts, loading } = this.props.plaid;

    let dashboardContent;
    if (loading) {
      dashboardContent = <p>Loading...</p>;
    } else if (accounts === null || Object.keys(accounts).length === 0) {
      dashboardContent = (
        <div>
          <h4>
            <b>Welcome,</b> User
          </h4>
          <p className="flow-text grey-text text-darken-1">
            To get started, link your first bank account below
          </p>
          <PlaidLink
            clientName="Mosaic"
            className="btn btn-large waves-effect waves-light hoverable blue accent-3"
            env="sandbox"
            product={["auth", "transactions"]}
            publicKey="0c3ff69a2efea552189de8b7fbbc0f"
            onSuccess={this.handleOnSuccess}
            style={{
              width: "185px",
              letterSpacing: "1.5px",
              borderRadius: "3px",
              marginTop: "1rem"
            }}
          >
            Link Account
          </PlaidLink>
          <button
            style={{
              width: "185px",
              borderRadius: "3px",
              letterSpacing: "1.5px",
              marginTop: "1rem"
            }}
            onClick={this.onLogoutClick}
            className="btn btn-large waves-effect waves-light hoverable red accent-3"
          >
            Logout
          </button>
        </div>
      );
    } else {
      dashboardContent = <Transactions accounts={accounts} />;
    }

    return (
      <div className="container">
        <div className="row">
          <div className="col s12 center-align">{dashboardContent}</div>
        </div>
      </div>
    );
  }
}

Dashboard.propTypes = {
  logoutUser: PropTypes.func.isRequired,
  getAccounts: PropTypes.func.isRequired,
  addAccount: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  plaid: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth,
  plaid: state.plaid
});

export default connect(
  mapStateToProps,
  { logoutUser, getAccounts, setAccountsLoading, addAccount }
)(Dashboard);

有人知道为什么我的getAccounts 操作中的dispatch(setAccountsLoading) 没有正确更新加载状态吗?

【问题讨论】:

  • 只需将dispatch(setAccountsLoading); 替换为dispatch(setAccountsLoading());
  • 哇,真不敢相信我错过了……这确实是问题所在。非常感谢@VassilisPallas!

标签: javascript reactjs redux


【解决方案1】:

正如Vassilis Pallas 在评论中提到的,函数调用后的括号丢失了,所以你应该有dispatch(setAccountsLoading()) 而不是dispatch(setAccountsLoading)

另外一个话题,我想推荐Redux Promise Middleware来简化在Redux中使用requests,你只需要dispatch request promise作为payload,这个包会为你处理,dispatch Pending, Fulfilled and Rejected action取决于通过的 Promise 的决议。

这极大地帮助我简化了异步 Redux 代码,尤其是在与 Type to Reducer 之类的代码配对时,正如 reducers documentation of Redux Promise Middleware 中所建议的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    相关资源
    最近更新 更多