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

React开发待办App时出现Uncaught TypeError报错求助

React 待办应用报错:Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

执行npm start后触发该报错,相关代码如下:

App.js 代码

import React from 'react';
import './App.css';
import AddItem from './addItem';
import Items from './list';
import './events';
function App() {
  return (
    <body>
    <h1>
        To Do List
      </h1>
    <div >
      
      <AddItem/>
      <Items/>
    </div>
    
    </body>
     
  );
}

export default App;

events.js 代码

let addBtn=document.getElementById('add');
let removeBtn=document.getElementById('remove');
let listOfItems=document.getElementById('items');
let addText=document.getElementById('addText');
let removeText=document.getElementById('removeText');
addBtn.addEventListener('click',add);
function add(){
  
    if(addText.value===''){
alert("Type the item you want to add first");
    }else{
let added=document.createElement('LI');
let addedTextNode=document.createTextNode(addText.value);
added.appendChild(addedTextNode);
listOfItems.appendChild(added);
localStorage.setItem('items',added.innerHTML);
}


}

问题根源

  1. DOM元素未加载完成:events.js在模块加载时立即执行document.getElementById,此时React组件还没完成渲染,DOM节点(比如addBtn)还不存在,导致获取结果为null,调用addEventListener触发报错。
  2. 开发范式冲突:混用原生DOM操作和React组件化逻辑,违背了React"状态驱动UI"的核心原则,容易引发时序问题和维护困难。

修复方案

1. 移除events.js文件

React不需要单独的原生事件监听文件,所有交互逻辑应整合到组件内部。

2. 重构AddItem组件,内置添加逻辑

修改addItem.js,通过React的状态管理和事件绑定实现添加功能:

import React, { useState } from 'react';

function AddItem({ onAddItem }) {
  const [inputText, setInputText] = useState('');

  const handleAddClick = () => {
    if (!inputText.trim()) {
      alert("Type the item you want to add first");
      return;
    }
    onAddItem(inputText);
    setInputText(''); // 清空输入框
  };

  return (
    <div>
      <input
        id="addText"
        type="text"
        value={inputText}
        onChange={(e) => setInputText(e.target.value)}
        placeholder="输入待办事项"
      />
      <button id="add" onClick={handleAddClick}>添加</button>
    </div>
  );
}

export default AddItem;

3. 在App组件中维护待办状态

修改App.js,负责管理待办列表的状态,并同步到localStorage:

import React, { useState, useEffect } from 'react';
import './App.css';
import AddItem from './addItem';
import Items from './list';

function App() {
  // 从localStorage加载初始待办数据
  const [items, setItems] = useState(() => {
    const saved = localStorage.getItem('items');
    return saved ? JSON.parse(saved) : [];
  });

  // 状态变化时自动保存到localStorage
  useEffect(() => {
    localStorage.setItem('items', JSON.stringify(items));
  }, [items]);

  // 处理新增待办的逻辑
  const handleAddItem = (newItem) => {
    setItems(prev => [...prev, newItem]);
  };

  return (
    <div className="App">
      <h1>To Do List</h1>
      <AddItem onAddItem={handleAddItem} />
      <Items items={items} />
    </div>
  );
}

export default App;

4. 重构Items组件渲染列表

修改list.js,接收父组件传递的items并渲染:

import React from 'react';

function Items({ items }) {
  return (
    <ul id="items">
      {items.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
}

export default Items;

额外注意事项

  • React组件的返回值必须是单个根元素,原代码中返回<body>不符合规范,改用<div>或React片段<>包裹。
  • 避免直接操作DOM,所有UI更新通过修改状态实现,这是React的核心开发模式。
  • 存储到localStorage时,使用JSON.stringify和JSON.parse处理数组,确保完整保存整个待办列表,而非单个元素的HTML内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 16:05:43