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

Time:11-30

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.

CodePudding user response:

Updated

You can try this:

  const handleSubmitNewTodo = () => {
    let newTodos = [...todos];
    console.log(newTask, newTodos);
    if (newTask) {
      newTodos.push(newTask);
      setTodos(newTodos);
      setNewTask(undefined);
    }
  };
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

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

CodePudding user response:

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);
  };
  • Related