Home > Software engineering >  Uncaught TypeError: variable is not iterable
Uncaught TypeError: variable is not iterable

Time:01-20

i was doing a todo list app on React, and, tring to handle the changes i got the following error: Uncaught TypeError: prevTodos is not iterable

My handle function:

  function handleAddTodo(e) {
    const name = todoNameRef.current.value;
    if (name === '') return;
    setTodos((prevTodos) => {
      return [...prevTodos, { id: v4(), name: name, complete: false }];
    });
    todoNameRef.current.value = null;
  }

Full Code:

import React, { useState, useRef, useEffect } from "react";
import TodoList from "./TodoList";
import { v4 } from "uuid";

const LOCAL_STORAGE_KEY = 'todoApp.todos';

function App() {
  const [todos, setTodos] = useState([]);
  const todoNameRef = useRef();

  useEffect(() => {
    const storedTodos = localStorage.getItem(LOCAL_STORAGE_KEY);
    if (storedTodos) setTodos(storedTodos);
    setTodos();
  }, []);

  useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos));
  }, [todos]);

  function handleAddTodo(e) {
    const name = todoNameRef.current.value;
    if (name === '') return;
    setTodos((prevTodos) => {
      return [...prevTodos, { id: v4(), name: name, complete: false }];
    });
    todoNameRef.current.value = null;
  }

  return (
    <>
      <TodoList todos={todos} />
      <input ref={todoNameRef} type="text" />
      <button onClick={handleAddTodo}>Add Todo</button>
      <button>Clear Complete</button>
      <div>0 left to do</div>
    </>
  );
}

export default App;

CodePudding user response:

This line is a problem

const storedTodos = localStorage.getItem(LOCAL_STORAGE_KEY);

you should parse the value before setting:

const storedTodos = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY))

CodePudding user response:

I haven't ran the code or tested anything but I think it's just the way your calling setTodos. Instead of passing in an anonymous function I would define the new todo list first, then use it to set the state. Try something like this.

function handleAddTodo(e) {
    const name = todoNameRef.current.value;
    if (name === '') return;
    const newTodos = [...prevTodos, { id: v4(), name: name, complete: false }];
    setTodos(newTodos);
    todoNameRef.current.value = null;
  }
  

You could probably get away with this too.

function handleAddTodo(e) {
    const name = todoNameRef.current.value;
    if (name === '') return;
    setTodos([...prevTodos, { id: v4(), name: name, complete: false }]);
    todoNameRef.current.value = null;
  }

Hopefully that helps.

  • Related