2

i make a to do list and i have 2 problems.

The first one : When i write something on my input and i click on my button (addTask) i need to click 2 times to have the result on my console.log . How i can do to have the result directly whn i click the first time ?

The second one : Nothing is rendered on my .map but all my values are on my array todoList . Did i do something wrong ?

function Task() {
  const [task, setTask] = useState("");
  const [encours, setEncours] = useState("en cours");
  const [todoList, setTodoList] = useState([]);

  const switchEnCours = () => {
    setEncours("terminé");
  };

  const deleteTask = () => {
    setEncours("supprimée");
  };

  const handleInput = (e) => {
    e.preventDefault();
    setTask(e.target.value);
  };
  const AddTask = (e) => {
    setTodoList([...todoList, task]);

    console.log(todoList);
  };

  return (
    <div>
      <input onChange={handleInput}></input>
      <button onClick={AddTask}>Valider</button>
      <div className="DivColonne">
        <div className="Colonne">
          <h1>Tâche à faire</h1>
          {todoList !== "" ? (
            todoList.map((insertTask) => {
              <div>
                <p>{insertTask}</p>
                <button onClick={switchEnCours}>{encours}</button>
              </div>;
            })
          ) : (
            <div></div>
          )}
        </div>
        <div className="Colonne">
          <h1>Tâche en cours</h1>
          {encours === "terminé" ? (
            <div>
              {todoList.map((insert) => {
                return (
                  <div>
                    <p>{insert}</p>
                    <button onClick={deleteTask}>{encours}</button>
                  </div>
                );
              })}
            </div>
          ) : (
            <div></div>
          )}
        </div>
        <div>
          <h1>Tâches terminées</h1>
          {encours === "supprimée" ? (
            <div>
              <p>{todoList}</p>
            </div>
          ) : (
            <div></div>
          )}
        </div>
      </div>
    </div>
  );
}

export default Task;
Xwingoga06
  • 99
  • 1
  • 10

5 Answers5

2

React state updates are asynchronously processed. This means you cannot console log the state right after an update has been enqueued and expect to see the updated value. Use a useEffect hook with dependency on the state you are updating to log state updates.

useEffect(() => console.log(todoList), [todoList]);

You are also not returning JSX when you are mapping the todos.

{todoList.map((insertTask) => {
  <div>
    <p>{insertTask}</p>
    <button onClick={switchEnCours}>{encours}</button>
  </div>;
})}

Should be

{todoList.map((insertTask) => {
  return (
    <div>
      <p>{insertTask}</p>
      <button onClick={switchEnCours}>{encours}</button>
    </div>
  );
})}

or directly returned

{todoList.map((insertTask) => (
  <div>
    <p>{insertTask}</p>
    <button onClick={switchEnCours}>{encours}</button>
  </div>
))}

Don't forget that when mapping lists and arrays in React to use a React key. If your tasks don't have a unique property then I highly suggest adding a GUID to each todo when it's created.

Example:

{todoList.map((insertTask) => (
  <div key={task.id}>
    <p>{insertTask}</p>
    <button onClick={switchEnCours}>{encours}</button>
  </div>
))}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

todoList is array you need iterate here check https://reactjs.org/docs/lists-and-keys.html

<div>
          <h1>Tâches terminées</h1>
          {encours === "supprimée" ? (
            <div>
              {todoList.map(value => <p>{value}</p>}
            </div>
          ) : (
            <div></div>
          )}
        </div>
Shubham Dhumal
  • 125
  • 1
  • 9
0

About console.log, you printing results after you change state, state updating is async, so it won't happen instantly. Can change to

  const AddTask = (e) => {
    const newList = [...todoList, task]
    console.log(newList);
    setTodoList(newList);
  };

About second part, this condition is redundant {todoList !== "" ? ( todoList is an Array, if it's empty .map never get executed.

Can you comment out this and check {encours === "terminé" ? ( ?

Also can't print Array in jsx

<div>
    // <p>{todoList}</p>
    <p>{JSON.stringify(todoList, null, 2)</p> --< try this
 </div>
0

There are bunch of wrong things you have done in your code.

1- Since the process of setting a state is Asynchronous, logging the todoList state right after the setTodoList won't give you the latest version of it.

To log the latest version of your state, you have to register an effect:

React.useEffect(() => console.log(todoList), [todoList])

2- It's better to use setTodoList(todoList => [...todoList, task]).

3- Since todoList is an array, checking todoList !== "" is redundant and it will always pass.

4- You missed to return the DOM Node here:

todoList.map((insertTask) => {
  <div>
    <p>{insertTask}</p>
    <button onClick={switchEnCours}>{encours}</button>
  </div>;
})

5- Also you missed to use a decent key prop on loops:

todoList.map((insertTask) => {
  <div key={insertTask.toString()}>
    <p>{insertTask}</p>
    <button onClick={switchEnCours}>{encours}</button>
  </div>;
})

Check out this article for more information on this matter.


And for your main question "How to empty your state" you have to use a controlled text input instead of uncontrolled one:

<input onChange={handleInput} value={task} />

Then to empty your state, all you have to do is:

const AddTask = (e) => {
  setTodoList(state => [...state, task]);
  setTask("");
};
  • Point 5 is slightly incorrect, arrays of renderable JSX don't need to be mapped. I.e. arrays of strings, numbers, JSX, etc... even mixed content of renderable JSX is fine and doesn't need to be mapped. – Drew Reese Sep 21 '21 at 09:12
  • @DrewReese oh, yeah you're right. I was talking in his case. I'll edit it. – Mostafa Shamsitabar Sep 21 '21 at 09:15
0

your 1st problem is that you show data in "console.log()" and the nature of console.log that it shows the previous value/data(state), it's better that you used "alert()" instead.

Dawood Ahmad
  • 476
  • 4
  • 13