首页 > 解决方案 > Redux:根据 Actions 改变 Reducer 中初始状态的不同部分

问题描述

我有以下减速器:

const initialState = {}

const dishReducer = (state = initialState, action) => {
    switch (action.type) {
      case 'LOAD_DISHES': 
        return (action.dishes)
    
      case 'LOAD_DISHES_ERROR': 
        console.log("load dishes error")
        return state
      case 'LOAD_DISHES_SUCCESS': 
        console.log("load dishes success")
        return state
      default:
        return state;
    }
  };

  export default dishReducer;

以及以下操作:

import {database} from '../../config/fbConfig'

export const startLoadingDishes = (dishes) => {
    return (dispatch) =>{
        return database.ref('products-dishes').once('value').then((snapshot) => {
            let dishes = {}
            snapshot.forEach((childSnapshot) => {
                let parentkey = childSnapshot.key
                let dishArray = [];
                childSnapshot.forEach((dish) =>{
                        dishArray.push(dish.val())
                    });
                dishes[childSnapshot.key] = dishArray;
            })
    
            dispatch(loadDishes(dishes))
        }).then(() => {
            dispatch({ type: 'LOAD_DISHES_SUCCESS' });
          }).catch(err => {
            dispatch({ type: 'LOAD_DISHES_ERROR' }, err);
          });
    }

}

export const loadDishes = (dishes) => { 
    return {
        type: 'LOAD_DISHES',
        dishes               
    }
}

在某个组件的 componentDidLoad() 中调用了“startLoadingDishes”操作。但是,我想更改我的 discReducer 的初始状态,以便它包含附加信息,如下所示:

const initialState = {
    value : {},
    loaded: false,
    loading: false,
    error: false
}

所以现在由 reducer 返回的 'action.dishes' [在 'LOAD_DISHES' 情况下] 应该放在状态的 'value' 部分,而不是整个状态。此外,如果菜肴之前已加载,则状态的“已加载”部分应设置为 true,依此类推。我知道这相当简单,但由于我是 React+Redux 的新手,我不知道如何正确更改 Action/Reducer 代码(同时保持状态不变性)。任何帮助表示赞赏。

标签: javascriptreactjsreduxredux-reducers

解决方案


我最初问了这个问题,这是我解决它的方法(虽然不确定这是否是“最好的”方法):

新的减速器文件:

const initialState = {
    value : {},
    loaded: false,
    loading: false,
    error: false
}

const dishReducer = (state = initialState, action) => {
    switch (action.type) {
      case 'LOAD_DISHES': 
        return {
          value: action.dishes,
          loading: !state.loading,
          loaded: false,   //this might need to be set to true
          error: false
        }
    
      case 'LOAD_DISHES_ERROR': 
        console.log("load dishes error")
        return {
          ...state,   //or: state.value, as the other parts of state are being overwritten below
          loaded: false,
          loading: false,
          error: true
        }
      case 'LOAD_DISHES_SUCCESS': 
        console.log("load dishes success")
        return { 
          ...state,  //better: state.value
          loaded: true,
          loading: false,
          error: false
        }
      default:
        return state;
    }
  };

  export default dishReducer;

动作文件没有变化。

现在,在“主要”组件中,我最初是这样访问状态的:

class Main extends Component {

  componentDidMount() { 
    this.props.startLoadingDishes();
  }

  render() {

    return (
      //some code
    )
  }
}

const mapStateToProps = (state) => {
  return {
    dishes: state.dishes  //to access dishes: dishes.value
  }
}

export default connect(mapStateToProps, actions)(Main)

主要组件代码也保持不变,不同之处在于现在我使用 'dishes.value' 而不仅仅是 'dishes' 从状态中访问菜肴的值(并且为加载的 disces.loaded 等等)。现在 componentDidMount 内部的动作调用者如下:

componentDidMount() { 
    if(!this.props.dishes.loaded){
      this.props.startLoadingDishes();
      console.log("loading dishes from database")
    }
  }

推荐阅读