Search code examples
reactjsinputonclickreducerspayload

updating state through dispatch function


I am building a to do list. One of the features is to be able to add tasks to the do list via user input. I am holding an initial list of todos in state in a reducer pattern. There is an action called ADD_ITEM that should add a new task to the todo list. However, this dispatch function does not appear to be working. When I click on the button that should add a new task to my todo list, it only adds a blank <li> to the list. When I try to use the user input to add a new todo and console.log newItemText which should be set by the input, it gets logged as undefined. Can someone take a look at the code and tell me why this is happening?

TodoList.js:

import React, { useState, useReducer } from"react";

import Todo from "./Todo";
import { initialState, reducer } from "../reducers/todoReducer";
import { ADD_ITEM } from "../actions/actions";


const TodoList = props => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const [newItemText, setNewItemText] = useState("");

    const handleChanges = e => {
        console.log(e.target.value)
        setNewItemText(e.target.vaue);
    };

    console.log(newItemText);

    return (
        <div>
            <ul className="task-list">
                {state.map(task => (
                    <Todo key={task.item} task={task} />
                ))}
            </ul>
            <input
                className="add-input"
                name="todo"
                type="text"
                placeholder="Enter a task"
                value={newItemText}
                onChange={handleChanges}
            />
            <button
                className="add-button"
                onClick={() => dispatch({ type: ADD_ITEM, payload: newItemText })}
            >
                Add a Task
            </button>
            <button
                className="add-button"
                onClick={null}
            >
                Remove Completed
            </button>
            </div>
    )
}

export default TodoList;

todoReducer.js:

import { ADD_ITEM, TOGGLE_COMPLETED, REMOVE_COMPLETED } from "../actions/actions";

export const initialState = [
    { item: 'Learn about context API', completed: false, id: 1}, 
    { item: 'Learn about reducers', completed: false, id: 2},
    { item: 'complete context API project', completed: false, id: 3},
    { item: 'complete reducers project', completed: false, id: 4}
];

export const reducer = (state = initialState, action) => {
    console.log(action)
    switch(action.type) {
        case ADD_ITEM:
            return [
                ...state,
                {
                    item: action.payload,
                    completed: false,
                    id: Date.now()
                }
            ]
        case TOGGLE_COMPLETED:
            const toggledState = [...state];
            toggledState.map(item => {
                if(item.id === action.payload) {
                    item.completed = !item.completed;
                }
            })
            state = toggledState;
            return state;
        case REMOVE_COMPLETED:
            return state.filter(item => !item.completed);
        default:
            return state;
    }
}

Solution

  • Inside handleChanges function, you misspelt value:

    setNewItemText(e.target.vaue);

    ;)