You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Todo应用报错:todo未定义问题求助

React Todo应用报错:Uncaught TypeError: todo is undefined(footer.js第15行)

问题背景

开发React Todo应用时拆分了多个组件,运行时应用无法正常显示,控制台始终在footer.js第15行抛出「Uncaught TypeError: todo is undefined」错误。已通过useState维护todo数组并作为props传递给TodoCounter组件,尝试过重命名props、调整组件调用位置,但问题未解决。

相关代码

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() {
  // 创建todo状态
  const [todo, setTodo] = useState([]);

  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;
import React, { useEffect, useState } from 'react';
import './App.css';

function TodoCounter(props) {
  const { todo } = props;
  const [completed, setCompleted] = useState(0);
  const [notCompleted, setNotCompleted] = useState(0);

  // 统计已完成和未完成的todo数量
  function counttodos(props) {
    const { todo } = props;
    return {
      completed: todo.filter((todo) => todo.isChecked).length,
      notCompleted: todo.filter((todo) => !todo.isChecked).length,
    };
  }

  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;

错误原因分析

问题出在counttodos函数的调用和定义不匹配:

  • counttodos函数定义时期望接收一个包含todo属性的对象,并通过const { todo } = props;解构获取todo数组。
  • 但在useEffect中调用该函数时,直接传入了todo数组本身,而非包含todo的对象。此时counttodos里的props是数组,解构props.todo自然会得到undefined,后续执行todo.filter时就会抛出类型错误。

另外,原代码中解构的notcompleted拼写错误,与函数返回的notCompleted不一致,会导致未完成数量始终为0;同时filter回调参数名和外部todo数组重名,容易造成混淆。

修复方案

方案一:调整函数调用方式

在useEffect中调用counttodos时,把todo数组包装成对象传入,同时修正拼写错误:

useEffect(() => {
  const { completed, notCompleted } = counttodos({ todo });
  setCompleted(completed);
  setNotCompleted(notCompleted);
}, [todo]);

方案二:简化函数参数定义

直接让counttodos接收todo数组作为参数,避免解构对象,同时修改回调参数名避免重名:

// 修改counttodos函数
function counttodos(todo) {
  return {
    completed: todo.filter((item) => item.isChecked).length,
    notCompleted: todo.filter((item) => !item.isChecked).length,
  };
}

// 对应修改useEffect调用
useEffect(() => {
  const { completed, notCompleted } = counttodos(todo);
  setCompleted(completed);
  setNotCompleted(notCompleted);
}, [todo]);

额外优化建议

可以省去useEffect和额外的state,直接基于todo数组计算统计值,代码更简洁高效:

function TodoCounter(props) {
  const { todo } = props;
  const completed = todo.filter(item => item.isChecked).length;
  const notCompleted = todo.length - completed;

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

内容的提问来源于stack exchange,提问作者Davidino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:31:58