Redux 用户教育者与状态管理

Redux 用户教育者与状态管理,redux,state,use-reducer,Redux,State,Use Reducer,嘿,伙计们,我正在学习useReducer钩子,在大多数情况下,它似乎与redux非常相似(不包括发送到商店的操作等) 当我遇到更复杂的状态管理情况时,我似乎总是遇到问题,那就是试图以我想要的方式改变我的状态。在我的代码中,我基本上是让用户选择一首曲目,并将其添加到最喜爱的歌曲列表中。我的代码似乎正在替换状态,而不是添加到状态 这是我的初始状态和useReducer,最后是add函数(当按下下面的按钮时,它会发送一个要添加到列表中的曲目) const initialState = { nam

嘿,伙计们,我正在学习useReducer钩子,在大多数情况下,它似乎与redux非常相似(不包括发送到商店的操作等)

当我遇到更复杂的状态管理情况时,我似乎总是遇到问题,那就是试图以我想要的方式改变我的状态。在我的代码中,我基本上是让用户选择一首曲目,并将其添加到最喜爱的歌曲列表中。我的代码似乎正在替换状态,而不是添加到状态 这是我的初始状态和useReducer,最后是add函数(当按下下面的按钮时,它会发送一个要添加到列表中的曲目)

const initialState = {
  name:'',
  duration:''
};

const [favorites, dispatch]=useReducer(reducer, initialState)



const add=(song)=>{
  dispatch({type:'ADD', payload:song})
  console.log(favorites)
}
这是让我困惑的部分。我的减速机里有这个

export const reducer=(song, action)=>{
  switch(action.type){
    case 'ADD':
    return {...song, name:action.payload}
}
这实际上是每次添加一个名为name:trackname的新对象,但我不想覆盖最后一项。我觉得我使用了错误的排列,也返回了错误的有效负载,可能吧

我的最终状态一直是这样

{name: "deep end", duration: ""}
when i want it to look something like this
``
[{name: "deep end", duration: ""}
{name: "ok", duration: ""}
{name: "testtrack", duration: ""}
]`

const initialState = {
  favorites:{
[ADD TRACKS HERE]
}
};
我试过把初始状态设置成这样

{name: "deep end", duration: ""}
when i want it to look something like this
``
[{name: "deep end", duration: ""}
{name: "ok", duration: ""}
{name: "testtrack", duration: ""}
]`

const initialState = {
  favorites:{
[ADD TRACKS HERE]
}
};
但似乎无法正确覆盖状态以便添加到数组中。它会不断覆盖最后一个状态。

Redux的指南是一个关于如何以不改变状态的方式更新嵌套数据的极好资源

对于
数组
有两种主要方法可以不可变地添加元素

  • 与:
  • 使用,它返回一个包含附加项的新数组(这不同于对数组进行变异并仅返回长度的数组)

  • 您可以决定您希望状态的形状。将数组存储到属性
    收藏夹中可以,但会给更新增加另一层复杂性

    export const reducer = (state, action) => {
      switch (action.type) {
        case "ADD":
          return { 
            ...state, 
            favorites: [...state.favorites, action.payload]
          };
        default:
          return state;
      }
    };
    
    const initialState = {
      favorites: [] // initial state has an empty array
    };
    
    const [state, dispatch] = useReducer(reducer, initialState);
    
    // here favorites is just a property of state, not the whole state
    const favorites = state.favorites;
    
    我建议
    state
    应该只是
    收藏夹的数组本身

    export const reducer = (favorites, action) => {
      switch (action.type) {
        case "ADD":
          return [...favorites, action.payload]
        default:
          return favorites;
      }
    };
    
    // favorites is the whole state
    // initial state is an empty array
    const [favorites, dispatch] = useReducer(reducer, []);
    

    无论哪种情况,我们都希望
    action.payload
    是一个完整的歌曲对象,而不仅仅是名称

    dispatch({ type: "ADD", payload: { name: "Deep End", duration: "3:22" } });
    
    你可以把它提取到一个helper函数中。用Redux术语来说,我们称这个函数为


    查看关于不可变更新模式的指南:您想使用concat或spread语法来更新状态的一个属性,即数组。或者只是使数组成为整个状态!是的,这是我的问题。不可变和深度复制。必须习惯于此!我最初的状态有一个对象,本质上是一个数组对象。需要在减速机中执行类似的操作返回{…歌曲,收藏夹:[…歌曲.收藏夹,操作.有效负载]}这种深嵌套的不可变内容对我来说是新的,但它清除了很多!谢谢你
    const addFavorite = (name, duration) => ({
      type: "ADD",
      payload: { name, duration }
    });
    
    dispatch(addFavorite("Deep End", "3:22"));