【问题标题】:React-Redux: Action is Dispatched but Reducer is not updating the stateReact-Redux:操作已调度,但 Reducer 未更新状态
【发布时间】:2021-08-08 17:56:04
【问题描述】:

我正在尝试检查我的商店是否已上线。为此,我正在通过 redux 进行 API 调用以在 BE 中检查它,如果它是真的,我会将它重定向到仪表板。我能够从 BE 成功获取数据,并且在成功时调用了 checkIsStoreOnboardedSuccess(),但在减速器中,状态不会更新为减速器中的 CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_SUCCESS 状态。

action.js

import * as actionTypes from './index';
import API from '../../api';

export const clearCheckIsStoreOnboarded = () => {
  return {
    type: actionTypes.CLEAR_CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING,
  };
};

export const checkIsStoreOnboarded = (payload) => {
  return (dispatch) => {
    dispatch(checkIsStoreOnboardedInitiate());
    API.getAccountSettings(payload)
        .then((response) => {
            checkIsStoreOnboardedSuccess(response.data);
        })
        .catch((err) => {
            checkIsStoreOnboardedFailure(err);
        });
  };
};

const checkIsStoreOnboardedInitiate = () => {
  return {
    type: actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_START,
  };
};
const checkIsStoreOnboardedSuccess = (data) => {
  return {
    type: actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_SUCCESS,
    data: data,
  };
};
const checkIsStoreOnboardedFailure = (err) => {
  return {
    type: actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_FAIL,
    data: err,
  };
};

reducer.js

import * as actionTypes from '../actions';

const initialState = {
  isLoading: true,
  isError: false, 
  isDone: false,
  data: [],
  error: null,
};

const clearCheckIsStoreOnboarded = () => {
  return initialState;
};

const checkIsStoreOnboardedStart = (state) => {
  return { ...state, isLoading: true, error: null, isError: false };
};

const checkIsStoreOnboardedSuccess = (state, action) => {
  return { ...state, data: action.data, isDone: true, isLoading: false };
};

const checkIsStoreOnboardedFailure = (state, action) => {
  return { ...state, error: action.data, isLoading: false, isError: true };
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.CLEAR_CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING:
      return clearCheckIsStoreOnboarded();
    case actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_START:
      return checkIsStoreOnboardedStart(state);
    case actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_SUCCESS:
      return checkIsStoreOnboardedSuccess(state, action);
    case actionTypes.CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_FAIL:
      return checkIsStoreOnboardedFailure(state, action);
    default:
      return state;
  }
};

export default reducer;

actionTypes.js

export const CLEAR_CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING = 'CLEAR_CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING';
export const CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_START = 'CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_START';
export const CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_SUCCESS = 'CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_SUCCESS';
export const CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_FAIL = 'CHECK_IS_STORE_ONBOARDED_FOR_ONBOARDING_FAIL';

onboard.js


import React, { useState, useEffect } from 'react';
import { withCookies } from 'react-cookie';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';

import Crew from './Crew';
import Service from './Services';
import Address from './Address';
import { useStyles } from './css/index.css';
import Header from './header';
import Stepper from './stepper';
import { getStoreID } from '../../../utils';
import {
  clearCheckIsStoreOnboarded,
  checkIsStoreOnboarded,
} from '../../../store/actions/check-is-store-onboarded-for-onboarding'

import Loader from '../../../components/CircularProgressLoader';

const OnboardScreen = ({ 
  cookies,
  clearCheckIsStoreOnboarded,
  checkIsStoreOnboarded,
  checkIsStoreOnboardedData,
}) => {
 
  const [step, setStep] = useState(0);
  // eslint-disable-next-line no-unused-vars
  const [width, isDesktop] = useWindowWitdh();
  const classes = useStyles(isDesktop);
  const store_id = getStoreID(cookies);


  useEffect(() => {
    checkIsStoreOnboarded({
      store_id,
    });
  }, []);
  useEffect(() => () => clearCheckIsStoreOnboarded(), []);


  if(checkIsStoreOnboarded.isDone){
   <Redirect to='/dashboard'>
  }


  const updateStep = () => {
    const updatedStep = step + 1;
    setStep(updatedStep);
  };
  const onboardingScreenToRender = () => {
    switch (step) {
      case 0:
        return (
          <Crew />
        );
      case 1:
        return (
          <Service />
        );
      case 2:
        return <Address />;
    }
  };
  return (
    <div className={classes.container}>
      <Header isDesktop={isDesktop} />
      <div className={classes.contentOfContainer}>
          <div className={classes.titleHeader}>
            Onboarding
          </div>
        <Stepper stepNumber={step} setStepNumber={setStep} />
        {checkIsStoreOnboardedData.isLoading && <Loader />}
      </div>
    </div>
    // <OnboardLoader />
    );
  };
  

  const mapStateToProps = (state, ownProps) => {
    return {
      ...ownProps,
      checkIsStoreOnboardedData: state.checkIsStoreOnboardedForOnboardingReducer
    };
  };
  
  const mapDispatchToProps = (dispatch) => {
    return {
      checkIsStoreOnboarded: (payload) => dispatch(checkIsStoreOnboarded(payload)),
      clearCheckIsStoreOnboarded: () => dispatch(clearCheckIsStoreOnboarded()),
    };
  };
  
  export default connect(
    mapStateToProps,
    mapDispatchToProps,
  )(withCookies(OnboardScreen));

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    你需要dispatch你的行动:

    export const checkIsStoreOnboarded = (payload) => {
      return (dispatch) => {
        dispatch(checkIsStoreOnboardedInitiate());
        API.getAccountSettings(payload)
            .then((response) => {
                // here
                dispatch(checkIsStoreOnboardedSuccess(response.data));
            })
            .catch((err) => {
                // and here
                dispatch(checkIsStoreOnboardedFailure(err)(;
            });
      };
    };
    

    也就是说:您在这里编写了一种非常过时的 Redux 风格 - 在现代 Redux 中,所有这些可能只需要 1/4 的代码就可以实现。如果你只是在学习 Redux,那么你可能正在学习一个非常过时的教程。现代 Redux 不需要您编写动作类型字符串或动作创建者,并且您的 reducer 可以包含可变逻辑。此外,它不使用connect,除非您使用的是遗留类组件(您似乎没有这样做)。

    我真的推荐你阅读https://redux.js.org/tutorials/essentials/part-1-overview-concepts的官方 Redux 教程

    【讨论】:

    • 非常感谢您的回答。它有很大的帮助。当然,我会看看现代的 redux 并期待它的实现。
    • 如果有帮助,请点赞并接受答案:)
    猜你喜欢
    • 2021-01-08
    • 2019-12-04
    • 2022-06-21
    • 2018-08-04
    • 2017-01-19
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    相关资源
    最近更新 更多