Max Wolfen
Max Wolfen

Reputation: 2033

Filter deletes all state inside the Redux store

I have a little problem with filter of the Redux iteams store with reducers case DELETE_TODO.

So the problem is happen when I try to delete some of the elements inside the todo list. Deleting is work, but per click on some separate element to delete it, the whole todo list is gone. I cannt understand why.

I make the several tests to understand where is the problem located. What I got:

  1. The action work good, because the value come from it into reducers normally. Filter work.
  2. When the list in app had been deleted and I try to add some other todos, the app start crash with error - TypeError: Cannot read property 'todos' of undefined.

Plese, help someone if you can, because I'm already empty... :(

/* REDUCERS */

    import { combineReducers } from 'redux'
    import { ADD_TODO, ADDED_BUTTON, TOGGLE_BUTTON, EDIT_TODO, DELETE_TODO, FILTER_TODO_UP, FILTER_TODO_DOWN } from '../Variables/Variables'

    const initialState = {
    iteams: [{
        todos:[],
        buttons:[]
    }]
    }

    function TodoApp(state, action) {
    if (typeof state === 'undefined') {
        return initialState;
    }

    switch (action.type) {
        case ADD_TODO:
            console.log('Reduce',action.text);
            return Object.assign({}, state, {
                iteams: [{
                    todos: [
                        ...state.iteams[0].todos, 
                        {
                            id: action.id,
                            text: action.text,
                        }
                    ],
                    buttons: [
                        ...state.iteams[0].buttons, 
                        {
                            id: action.id,
                            text: action.text,
                            done: false
                        }
                    ]
                }]
            });
        case DELETE_TODO:
            return Object.assign({}, {
                iteams: state.iteams.filter(iteam => {
                    iteam.todos.id !== parseInt(action.id)
                })
            });
        default: 
            return state;
    }
    }



    export default TodoApp

/* ACTIONS */

import { ADD_TODO } from '../Variables/Variables'

let nextTodoId = 0;

function AddTodo(text) {
    console.log('Action', text);
    return {
        type: ADD_TODO,
        id: nextTodoId++,
        text,
        done: false
    }
};

function DeleteTodo(id) {
    return {
        type: DELETE_TODO,
        id
    }
};

export { AddTodo }

/* CONTAINER */

import { connect } from 'react-redux';
import TodoList from '../Components/TodoList/TodoList';
import { DeleteTodo } from '../Actions/AddTodo'

const mapStateToProps = state => ({
    iteams: state.iteams
});

const mapDispatchToProps = dispatch => ({
      todoFormDelete: todo => dispatch(DeleteTodo(todo))
});

export default connect(
    mapStateToProps, 
    mapDispatchToProps)(TodoList)

/* COMPONENT */

import React, {Fragment} from 'react';
import TodoIteam from '../TodoIteam/TodoIteam'
import ButtonToggle from '../ButtonToggle/ButtonToggle'

class TodoList extends React.Component {
handleDelete = (e) => {
    let target = e.target;
    let closestDelete = target.closest('span');
    let closestEdit = target.closest('button');

    if (closestDelete) {
        let index = closestDelete.parentNode.getAttribute('index');
        console.log('index', index);
        this.props.todoFormDelete(index);
    } else { 
        return 
    }
}

render(props) {
    return ( 
        <Fragment>
            {console.log('Hi', this.props.store.getState().iteams)}
            <div onClick={this.handleDelete}>
                {this.props.iteams.map((iteam, index) => {
                    return <TodoIteam key={index} {...iteam} />
                })}
            </div>
        </Fragment>
    );
}
}

export default TodoList;

Upvotes: 0

Views: 140

Answers (2)

Giang Le
Giang Le

Reputation: 7044

im so confused with your initialState. I think it must be this

const initialState = {
  iteams: {
    todos:[],
    buttons:[]
  }
}

and the ADD_TODO

case ADD_TODO:
  return Object.assign({}, state, {
    iteams: {
      todos: [
        ...state.iteams.todos, //Change here
        {
          id: action.id,
          text: action.text,
        }
      ],
      buttons: [
        ...state.iteams.buttons, //Change here
        {
          id: action.id,
          text: action.text,
          done: false
        }
      ]
    }
  })

and in the DELETE_TODO

case DELETE_TODO:
  return {
    iteams: {
      todos: state.iteams.todos.filter(iteam => iteam.id !== parseInt(action.id)),
      buttons: state.iteams.buttons.filter(button => button.id !== parseInt(action.id))
    }
  }

Upvotes: 1

Yossi
Yossi

Reputation: 6027

Why is iteams an array? (BTW, didn't you mean 'items'?)
When you add a 'todo', you add it to iteams[0].todos. However, when you filter in order to delete a 'todo', you go through the iteams array, and not through the todos array...

Seems to me (unless I don't understand what you intend to do) is that that the state should be:

iteams: {
  todos:[],
  buttons:[]
}

and when you delete an item, you should filter the iteams.todos array, not the iteams array.

Upvotes: 0

Related Questions