React开发TODO列表报appendChild is not a function错误
报错直接原因
你代码里的两个低级错误直接触发了appendChild is not a function:
const list = List.document.getElementsByClassName('.div-list')写法完全错误:List是你自定义的React函数组件,不是浏览器提供的DOM/全局对象,本身不存在document属性,这行代码的返回值是undefined,对undefined调用appendChild方法自然会抛出函数不存在的错误。- 就算你把这行改成
document.getElementsByClassName('.div-list')也选不到元素:getElementsByClassName的参数只需要传纯类名字符串,不需要带类选择器前缀.,带.的写法是querySelector/querySelectorAll的语法,这里传参不对会拿到空的元素集合,对集合调用appendChild也会报错。
根本逻辑问题
你在用原生JavaScript命令式操作DOM的思路写React,这是框架使用方式的根本错误:
React是声明式框架,所有界面渲染由数据状态驱动,你不需要手动创建DOM节点、追加节点,只需要维护好对应的数据,React会自动根据数据变化更新真实DOM。你手动操作DOM的写法不仅容易出错,后续React触发组件重渲染时,你手动追加的节点还会被虚拟DOM的对比逻辑直接覆盖删除。
正确实现代码
按照React状态驱动的思路改写即可,不需要任何原生DOM操作:
- 父组件(存放表单和状态)
import { useState } from 'react' import { List } from './List' export default function TodoApp() { // 存储三个输入框的绑定值 const [datos, setDatos] = useState({ text: '', amount: '', date: '' }) // 存储所有待办列表项 const [todoItems, setTodoItems] = useState([]) // 同步输入框值到状态 const handleInputChange = (e) => { setDatos({ ...datos, [e.target.name]: e.target.value }) } // 表单提交逻辑,对应原cargarDatos方法 const cargarDatos = (pool) => { pool.preventDefault() // 直接更新列表状态即可,不需要操作DOM const newItem = `${datos.text} ${datos.amount} ${datos.date}` setTodoItems([...todoItems, newItem]) // 提交后清空输入框 setDatos({ text: '', amount: '', date: '' }) } return ( <div> <form onSubmit={cargarDatos}> <input name="text" value={datos.text} onChange={handleInputChange} placeholder="待办内容" /> <input name="amount" value={datos.amount} onChange={handleInputChange} placeholder="数量" /> <input name="date" value={datos.date} onChange={handleInputChange} placeholder="日期" /> <button type="submit">添加待办</button> </form> {/* 把列表数据传给List组件渲染 */} <List items={todoItems} /> </div> ) }
- 改写后的List组件
import React from "react"; export function List ({ items }) { return ( <> <h2>List</h2> <div className={'div-list'}> {/* 遍历传入的列表数据,自动渲染对应节点 */} {items.map((item, idx) => ( <div className="item-List" key={idx}> {item} </div> ))} </div> </> ) }
新手写React牢记一个原则:只要你写的代码里出现了
document.createElement、appendChild、getElementById/ClassName这类直接操作真实DOM的代码,99%的概率是写法错了,优先考虑用状态+JSX遍历的方式实现需求。
内容的提问来源于stack exchange,提问作者exodus
相关产品推荐
相关产品推荐

