React-Redux: действие отправлено, но редьюсер не обновляет состояние

avatar
syed _khutub
8 августа 2021 в 17:56
41
1
0

Я пытаюсь проверить, подключен ли мой магазин к сети. для этого я делаю вызов 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));

Источник

Ответы (1)

avatar
phry
8 августа 2021 в 20:09
0

Вам необходимо 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, вы, вероятно, следуете очень устаревшему руководству. Modern Redux не требует от вас написания строк типа действия или создателей действий, а ваши редюсеры могут содержать изменяемую логику. Кроме того, он не использует connect, если только вы не работаете с компонентами устаревшего класса (чего вы, похоже, не делаете).

Я настоятельно рекомендую вам прочитать официальное руководство по Redux по адресу https://redux.js.org/tutorials/essentials/part-1-overview-concepts

.
syed _khutub
8 августа 2021 в 21:00
1

Большое спасибо за ваш ответ. Это очень помогло. Определенно, я проверю современный редукс и с нетерпением жду его реализации.

phry
8 августа 2021 в 22:27
0

Если это помогло, пожалуйста, проголосуйте и примите ответ :)