简体   繁体   中英

React / Typescript : pushing obj into array of object and undefined type

I'm beginnig my journey into TypeScript in React and to experiment what I've learn, I've try a simple Todo App. Everything is working fine except ONE things !

When I'm pushing 'newTask' When I'm hovering 'newTask' here's the hint (Google Trad from French):

The 'Todo | undefined 'is not attributable to the parameter of type' Todo '. Cannot assign type 'undefined' to type 'Todo'.

I guess it's related to something here:

let [newTask, setNewTask] = useState<Todo>();

because if I type useState<any>(); I don't have any error..

Here's the full code:

import React, { useState } from "react";

// INTERFACES
interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

export const TodoComponent = () => {
  // STATE
  const initialTodos: Todo[] = [
    { id: 0, text: "Todo 1", completed: false },
    { id: 1, text: "Todo 2", completed: true },
    { id: 2, text: "Todo 3", completed: false },
  ];

  const [todos, setTodos] = useState<Todo[]>(initialTodos);

  let [newTask, setNewTask] = useState<Todo>();

  // ACTIONS
  const handleClickOnComplete = (id: number, completed: boolean) => {
    const newTodos = [...todos];
    newTodos[id].completed = !completed;
    setTodos(newTodos);
  };

  const handleRemove = (todo: Todo) => {
    const newTodos = todos.filter((t) => t !== todo);
    setTodos(newTodos);
  };

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setNewTask({
      id: todos.length,
      text: event.target.value,
      completed: false,
    });
  };

  const handleSubmitNewTodo = () => {
    const newTodos = [...todos];
    console.log(newTask, newTodos);
    newTodos.push(newTask);
    setTodos(newTodos);
  };

  return (
    <div>
      <h1>Todo App !</h1>

      <div>
        {todos.map((todo) => {
          return (
            <div key={todo.id}>
              {todo.id} - {todo.text} -{" "}
              <input
                type="checkbox"
                checked={todo.completed}
                onChange={() => handleClickOnComplete(todo.id, todo.completed)}
              />
              <button onClick={() => handleRemove(todo)}>Remove task</button>
            </div>
          );
        })}
      </div>

      <hr />

      <div>
        <input placeholder="Add todo" type="text" onChange={handleChange} />
        <button onClick={handleSubmitNewTodo}>Add todo</button>
      </div>
    </div>
  );
};

Problem is in handleSubmitTodo

Thanks for your help and advices. Take care.

Updated

You can try this:

 const handleSubmitNewTodo = () => { let newTodos = [...todos]; console.log(newTask, newTodos); if (newTask) { newTodos.push(newTask); setTodos(newTodos); setNewTask(undefined); } };

I have added the setNewTask to undefined to maintain the initial state after adding the new todo to the todo list.

Like @jcalz suggests, adding a condition around the push seems to do the trick, is it the better way?

  const handleSubmitNewTodo = () => {
    const newTodos = [...todos];
    if (newTask) {
      newTodos.push(newTask);
    }
    setTodos(newTodos);
  };

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