admin管理员组

文章数量:1405392

I am having an issue with my ponent that should fetch accounts. I have a useEffect hook to run the request but only runs when I refresh. The useEffect hook runs my console.logs, but doesn't kick off the api request until I manually refresh. The general flow of the app is, once you log in, then kick off the request to show your table of accounts.

Component:

import React, { useEffect } from 'react';
import { func, object } from 'prop-types';
import { connect } from "react-redux";
import { getAllPlaidAccountsById } from "../../actions/accountActions";
import styles from "./DebtTable.css";


const DebtTable = ({ auth: { user },  getAllPlaidAccountsById, account: accounts }) => {
  useEffect(() => {
   getAllPlaidAccountsById(user._id);
  }, [getAllPlaidAccountsById]);

  if (accounts && accounts !== null) {
    return (
      <table className={styles.accountsTable}>
        <thead>
        <tr>
          <th>Account Name</th>
          <th>Account Type</th>
          <th>Interest Rate</th>
          <th>Min Payment</th>
          <th>Limit</th>
          <th>Balance</th>
          <th>Due Date</th>
        </tr>
        </thead>
        <tbody>
        {
          accounts.accounts.map((account) => {
            return account.map((acct, idx) => {
              const leftBottomCell = idx === accounts.length - 1 ? 'leftBottomCell' : '';
              const rightBottomCell = idx === accounts.length - 1 ? 'rightBottomCell' : '';

              return (
                <tr key={account.accountId}>
                  <td className={`${styles.accountName} ${styles[leftBottomCell]}`}>{acct.name}</td>
                  <td className={styles.accountType}>{acct.type}</td>
                  <td className={styles.interestRate}>-</td>
                  <td className={styles.minPayment}>-</td>
                  <td className={styles.accountLimit}>{`$${acct.balances.limit}`}</td>
                  <td className={styles.accountBalance}>{`$${acct.balances.current}`}</td>
                  <td className={`${styles.dueDate} ${styles[rightBottomCell]}`}>-</td>
                </tr>
              )
            })
          })
        }
        </tbody>
      </table>
    )
  }
  return null;
}
DebtTable.propTypes = {
  getAllPlaidAccountsById: func.isRequired,
  profile: object.isRequired,
  auth: object.isRequired
};

const mapStateToProps = (state) => ({
  profile: state.profile,
  account: state.account
});

export default connect(mapStateToProps, { getAllPlaidAccountsById })(DebtTable);

Redux Action:

import axios from "axios";
import {
  GET_ALL_PLAID_ACCOUNTS,
  GET_ALL_PLAID_ACCOUNTS_ERROR
} from "./types";

export const getAllPlaidAccountsById = (userId) => async dispatch => {
  try {
    const res = await axios.get(`/api/accounts/${userId}`);

    let creditCards = [];
    res.data.map(account => {
      if(account.type === 'credit') creditCards.push(account);
      return null;
    });

    dispatch({
      type: GET_ALL_PLAID_ACCOUNTS,
      payload: creditCards
    });

  } catch (err) {
    dispatch({
      type: GET_ALL_PLAID_ACCOUNTS_ERROR,
      payload: { msg: err }
    });
  }
};

Redux Reducer:

import {
  GET_ALL_PLAID_ACCOUNTS,
  GET_ALL_PLAID_ACCOUNTS_ERROR
} from '../actions/types';

const initialState = {
  account: null,
  accounts: [],
  error: {}
};

export default function(state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case GET_ALL_PLAID_ACCOUNTS:
      return {
        ...state,
        accounts: [payload, ...state.accounts],
        loading: false
      };
    case GET_ALL_PLAID_ACCOUNTS_ERROR:
      return {
        ...state,
        error: payload,
        loading: false
      };
    default:
      return state;
  }
}

I am having an issue with my ponent that should fetch accounts. I have a useEffect hook to run the request but only runs when I refresh. The useEffect hook runs my console.logs, but doesn't kick off the api request until I manually refresh. The general flow of the app is, once you log in, then kick off the request to show your table of accounts.

Component:

import React, { useEffect } from 'react';
import { func, object } from 'prop-types';
import { connect } from "react-redux";
import { getAllPlaidAccountsById } from "../../actions/accountActions";
import styles from "./DebtTable.css";


const DebtTable = ({ auth: { user },  getAllPlaidAccountsById, account: accounts }) => {
  useEffect(() => {
   getAllPlaidAccountsById(user._id);
  }, [getAllPlaidAccountsById]);

  if (accounts && accounts !== null) {
    return (
      <table className={styles.accountsTable}>
        <thead>
        <tr>
          <th>Account Name</th>
          <th>Account Type</th>
          <th>Interest Rate</th>
          <th>Min Payment</th>
          <th>Limit</th>
          <th>Balance</th>
          <th>Due Date</th>
        </tr>
        </thead>
        <tbody>
        {
          accounts.accounts.map((account) => {
            return account.map((acct, idx) => {
              const leftBottomCell = idx === accounts.length - 1 ? 'leftBottomCell' : '';
              const rightBottomCell = idx === accounts.length - 1 ? 'rightBottomCell' : '';

              return (
                <tr key={account.accountId}>
                  <td className={`${styles.accountName} ${styles[leftBottomCell]}`}>{acct.name}</td>
                  <td className={styles.accountType}>{acct.type}</td>
                  <td className={styles.interestRate}>-</td>
                  <td className={styles.minPayment}>-</td>
                  <td className={styles.accountLimit}>{`$${acct.balances.limit}`}</td>
                  <td className={styles.accountBalance}>{`$${acct.balances.current}`}</td>
                  <td className={`${styles.dueDate} ${styles[rightBottomCell]}`}>-</td>
                </tr>
              )
            })
          })
        }
        </tbody>
      </table>
    )
  }
  return null;
}
DebtTable.propTypes = {
  getAllPlaidAccountsById: func.isRequired,
  profile: object.isRequired,
  auth: object.isRequired
};

const mapStateToProps = (state) => ({
  profile: state.profile,
  account: state.account
});

export default connect(mapStateToProps, { getAllPlaidAccountsById })(DebtTable);

Redux Action:

import axios from "axios";
import {
  GET_ALL_PLAID_ACCOUNTS,
  GET_ALL_PLAID_ACCOUNTS_ERROR
} from "./types";

export const getAllPlaidAccountsById = (userId) => async dispatch => {
  try {
    const res = await axios.get(`/api/accounts/${userId}`);

    let creditCards = [];
    res.data.map(account => {
      if(account.type === 'credit') creditCards.push(account);
      return null;
    });

    dispatch({
      type: GET_ALL_PLAID_ACCOUNTS,
      payload: creditCards
    });

  } catch (err) {
    dispatch({
      type: GET_ALL_PLAID_ACCOUNTS_ERROR,
      payload: { msg: err }
    });
  }
};

Redux Reducer:

import {
  GET_ALL_PLAID_ACCOUNTS,
  GET_ALL_PLAID_ACCOUNTS_ERROR
} from '../actions/types';

const initialState = {
  account: null,
  accounts: [],
  error: {}
};

export default function(state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case GET_ALL_PLAID_ACCOUNTS:
      return {
        ...state,
        accounts: [payload, ...state.accounts],
        loading: false
      };
    case GET_ALL_PLAID_ACCOUNTS_ERROR:
      return {
        ...state,
        error: payload,
        loading: false
      };
    default:
      return state;
  }
}
Share Improve this question asked May 1, 2020 at 21:04 Chris McGlynnChris McGlynn 531 gold badge1 silver badge8 bronze badges 6
  • 1 your effect has a needless dependency of getAllPlaidAccountsById and a missing dependency of user._id – HMR Commented May 1, 2020 at 21:06
  • what do you mean needless, isn't getAllPlaidAccountsById necessary to be able to run? – Chris McGlynn Commented May 1, 2020 at 21:17
  • You import it so it's static and will never change – HMR Commented May 1, 2020 at 21:26
  • I imported it for the connect function which maps it to props. Are you saying that its not need to do that? Im a little confused as to what you are saying. Also, user.id is destructured from props, how is it missing? – Chris McGlynn Commented May 1, 2020 at 21:36
  • Ok, I see, you can add it to satisfy the linter but adding user._id is most important as it will run the effect when that changes. – HMR Commented May 1, 2020 at 21:39
 |  Show 1 more ment

1 Answer 1

Reset to default 3

The second parameter to useEffect is an array of variables that control when the useEffect executes. When the value of a variable in the array changes, then the useEffect will re-run. See https://reactjs/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

It seems likely that you want to get the accounts whenever a user._id changes, so you should pass an array containing that variable as the second argument to useEffect.

useEffect(() => {
  getAllPlaidAccountsById(user._id);
}, [user._id]);

本文标签: javascriptuseEffect runs api request after I refresh the pageStack Overflow