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

React组件默认/具名导出报错、useRef调用及Todo渲染问题求助

问题排查与解决方案

1. 导入导出错误修复

你最开始的报错是因为App.jsx中使用了默认导入语法引入List,但List.jsx最初是用命名导出的方式导出List,二者不匹配。
两种修复方案二选一:

  • 方案1:修改App.jsx的导入语法为命名导入:import { List } from './List',保留你最初的export {List, Render}导出方式
  • 方案2:修改List.jsx的导出为默认导出,和你后来改的一样:export default List; export { Render };,对应App.jsx的默认导入语法

2. useRef顶层调用错误修复

React Hook只能在函数组件内部顶层作用域或者自定义Hook中调用,你最开始把const inputRef = useRef()写在List组件外部,属于全局顶层调用,必然报错。
把inputRef移到List组件内部后,原来定义在全局的onClick、Render函数无法访问组件内部的inputRef变量,所以会报变量未定义的错误,同时你用全局变量todoItems存储待办数据,数据更新后无法触发React视图刷新,需要同步调整代码逻辑:

  • 用useState存储待办列表todoItems,替代全局变量
  • 把onClick逻辑移到List组件内部
  • 待办列表渲染逻辑和输入逻辑整合到同一个组件,不需要拆分两个独立的ReactDOM.render调用(你原来在index.js里调用两次ReactDOM.render会导致先渲染的App内容被后渲染的Render覆盖,且#list是嵌套在#root内部的,完全不需要两次渲染)

3. Render函数渲染问题解答

你写的Render函数不能正常渲染,原因有两个:

  1. forEach方法没有返回值,你需要用map方法来遍历返回React元素数组
  2. 遍历回调函数里的<h1>{item}</h1>没有写return,不会生成可渲染的元素
    修正后的渲染逻辑示例:
function Render({ todoItems }) {
  return todoItems.map((item, index) => <h1 key={index}>{item}</h1>);
}

完整修正代码

List.jsx

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

// 待办渲染组件
function Render({ todoItems }) {
  return todoItems.map((item, index) => <h1 key={index}>{item}</h1>);
}

// 输入组件
function List() {
  const inputRef = useRef();
  // 用useState存储待办列表,更新时自动触发视图刷新
  const [todoItems, setTodoItems] = useState([]);

  function onClick() {
    const newItem = inputRef.current.value.trim();
    if (!newItem) return;
    setTodoItems(prev => [...prev, newItem]);
    inputRef.current.value = '';
    console.log("Pushed item in the array!");
  }

  return (
    <div className="mainbox">
      <div className="inputdiv">
        <input
          type="text"
          ref={inputRef}
          placeholder="Enter Task..."
          className="textbox"
          id="taskName"
        />
        <button className="button" onClick={onClick}>+</button>
      </div>
      {/* 直接在List组件内渲染待办,不需要单独调用ReactDOM.render */}
      <div className="todo-list">
        <Render todoItems={todoItems} />
      </div>
    </div>
  );
}

export default List;
export { Render };

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/App';
import './styles.css';

// React 18以后推荐用createRoot语法,旧版本可以保留原来的render写法
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

App.jsx

import React from 'react';
import List from './List';

function App() {
  return (
    <div className="app">
      <List />
    </div>
  );
}

export default App;

index.html 调整

把嵌套在#root内部的#list移除,不需要额外的挂载节点:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="https://fonts.googleapis.com/css?family=McLaren|Montserrat&display=swap" rel="stylesheet" />
  <link rel="stylesheet" href="./src/styles.css">
  <title>Mandy's Todo-List App!</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:09:02