简体   繁体   中英

How to implement Reducer when store initial state is an Array?

I'm trying to understand React- Redux basics, but im stuck in this particular case:

My code actions:


let todoId = 1

export const ADDTODO = 'AddTodo'
export const REMOVETODO = 'RemoveTodo'
export const TOINPROGRESS = 'ToInProgress'
export const TODONE = 'ToDone'

export function addTodo(payload){
return{
   type: ADDTODO,
   payload:{
      status: 'Todo',
      id: todoId++,
      title: payload.title,
      date:payload.date,
      description:payload.description,
      place:payload.place     
        }                                
    }       
}

export function removeTodo(todoId){
    return{
        type: REMOVETODO,
        payload:todoId
    }
}

export function toInProgress(todoId){
    return{
        type: TOINPROGRESS,
        payload:todoId
    }
}

export function toDone(todoId){
    return{
        type: TODONE,
        payload:todoId
    }
}

My attemp to reduce code:


import { addTodo, removeTodo, toInProgress, toDone } from '../actions';
const initialState = [];

const todos = (state = initialState, action) => {
  switch(action.type) {   
      case 'AddTodo':      
        return[
          ...state, {           
            date:action.payload.date,
            description:action.payload.description,
            id:action.payload.id,
            place:action.payload.place,
            status:action.payload.status,
            title:action.payload.title,
            
          }          
        ]  
       
 case 'RemoveTodo':
     console.log(state)            
     return {
         ...state,
         todos: state.todos.filter(todo => todo.id  !== action.id)
     }


               
 case 'ToInProgress':             
     state.map(todo =>(todo.id===action.id)?{...todo,status:"InProgress"}:todo)     
         
 case 'ToDone':    
     state.map(todo =>(todo.id===action.id)?{...todo,status:"Done"}:todo)
                  
 default: 
     return state
  }
}

The only working method from todos reducer is AddTodo, cant figure out to RemoveTodo, ToInProgress & ToDo to work. Im getting an TypeError at RemoveTodo that says "Cannot read property 'filter' of undefined"... and undefined returns from the another two methods. Can you guys please give me some help? Regards in advance and please forget my bad grammar & coding

In your case state is an array, so state.todos will be undefined. You can fix 'RemoveTodo' case with something like

case 'RemoveTodo':          
    return state.filter(todo => todo.id  !== action.payload)

You missed return in other cases and you don't need to assign each property out of action.payload just pass it as is, this is how it would look

const todos = (state = initialState, action) => {
    switch (action.type) {
      case "AddTodo":
        return [...state, action.payload];
      case "RemoveTodo":
        return state.filter((todo) => todo.id !== action.payload.id);

      case "ToInProgress":
        return state.map((todo) =>
          todo.id === action.payload.id
            ? { ...todo, status: "InProgress" }
            : todo
        );

      case "ToDone":
        return state.map((todo) =>
          todo.id === action.payload.id ? { ...todo, status: "Done" } : todo
        );
      default:
        return state;
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM