Reputation: 2033
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:
action
work good, because the value
come from it into reducers
normally. Filter work.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
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
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