search

Home  >  Q&A  >  body text

Problem with undefined props in React

I wrote a to-do app in React. I create components for multiple parts. Now every time I try to run the app it doesn't show up.

I keep getting the error Uncaught TypeError: todo is undefined in footer.js:15.

I created a to-do list application and put all the to-do items into an array with usage status to-do items. This is the property I am passing in the component Todocounter in the footer of the file.

I tried renaming the prop and changing its position in the footer so it's called in the correct place.

This is app.js:

import React, { useState } from 'react';
import './App.css';
import InputTodos from './input.js';
import ListTodos from './list.js';
import TodoCounter from './footer.js';
import ClearButton from './clearbutton.js';

function App() {
  // create usestates for todos
  const [todo, setTodo] = useState([]);

  // render all components i have in diffrent files
  return (
    <div className="App">
      <div className="container">
        <div className="header">
          <InputTodos todo={todo} setTodo={setTodo} />
        </div>
        <div className="containerMid">
          <ListTodos todo={todo} />
        </div>
        <div className="footer">
          <TodoCounter todo={todo} />
        </div>
        <div className="buttonCleardiv">
          <ClearButton todo={todo} setTodo={setTodo} />
        </div>
      </div>
    </div>
  );
}

export default App;

This is footer.js:

import React, { useEffect, useState } from 'react';

import './App.css';

// use effect to show whenever the array will change from completed todos to not completed
function TodoCounter(props) {
  const { todo } = props;
  const [completed, setCompleted] = useState(0);
  const [notCompleted, setNotCompleted] = useState(0);

  // filter between completed todos and not completed todos with cheackking the bolean status
  function counttodos(props) {
    const { todo } = props;
    return {
      completed: todo.filter((todo) => todo.isChecked).length,
      notCompleted: todo.filter((todo) => !todo.isChecked).length,
    };
  }
  //with the useeffect hook set the todos on completed or not completed if sth changes on the todos
  useEffect(() => {
    const { completed, notcompleted } = counttodos(todo);
    setCompleted(completed);
    setNotCompleted(notcompleted);
  }, [todo]);

  return (
    <div>
      <p>Completed: {completed}</p>
      <p>Not Completed: {notCompleted}</p>
      <p>Todos: {todo.length} </p>
    </div>
  );
}

export default TodoCounter;

P粉949267121P粉949267121450 days ago542

reply all(1)I'll reply

  • P粉023326773

    P粉0233267732023-09-09 17:19:26

    Move the counttodos function out of the component so that it is not recreated on render. Because you pass todos as an argument to the function, and it's not wrapped in another object, you can use it directly without destructuring:

    // 用布尔状态检查已完成和未完成的待办事项进行过滤
    function counttodos(todos) {
      return {
        completed: todos.filter(todo => todo.isChecked).length,
        notCompleted: todos.filter(todo => !todo.isChecked).length,
      };
    }

    Call counttodos in the component itself and use the calculated value directly without storing it as state (see @HenryWoody's comment ):

    function TodoCounter({ todo }) {
      // 使用useEffect钩子在todos发生变化时设置已完成或未完成的todos
      const { completed, notcompleted } = counttodos(todo);
      
      return (
        <div>
          <p>已完成:{completed}</p>
          <p>未完成:{notCompleted}</p>
          <p>待办事项:{todo.length} </p>
        </div>
      );
    }

    reply
    0
  • Cancelreply