使用map()遍历数组/集合/列表时为何无法渲染内容?
问题:React 待办事项列表无法渲染内容
我经常遇到这个问题,但一直没找到合适的重复问题模板,大多是因为无关代码过多。本文将打造一个极简示例作为通用模板。
我有一个待办事项数组:
[ { id: 1, task: "go to the grocery store", isDone: false }, { id: 2, task: "walk the dog", isDone: true }, { id: 3, task: "buy a present for John", isDone: false }, ]
该数组的来源无关紧要。
它可以是硬编码的:
const todos = [ { id: 1, task: "go to the grocery store", isDone: false }, { id: 2, task: "walk the dog", isDone: true }, { id: 3, task: "buy a present for John", isDone: false }, ];
也可以来自服务器加载的静态文件:
import todos from "../data/todos.json";
还可以是Web API调用的结果:
useEffect(() => { fetch("https://api.example.com/v1.0/me/todo-items") .then(response => response.json()) .then(todos => setTodos(todos)) }, []);
或者是用户在应用逻辑中创建的:
function handleAddTodoSubmit(e) { e.preventDefault(); const todo = { id: nextID, task, isDone }; setTodos(todos => [...todos, todo]); setNextID(nextID => nextID + 1); setAddTodoDialogOpen(false); }
无论todos如何定义,以下代码都无法渲染待办事项:
function TodoList({ todos }) { return ( <ul> {todos.map((todo) => { <li key={todo.id}> <pre> <ASCIICheckbox isChecked={todo.isDone} /> {" "} {todo.task} </pre> </li> })} </ul> ); }
检查渲染后的结构可以看到,<ul>元素存在,但其中没有任何<li>元素。可运行下方代码片段自行测试:
const TODOS = [ { id: 1, task: "go to the grocery store", isDone: false }, { id: 2, task: "walk the dog", isDone: true }, { id: 3, task: "buy a present for John", isDone: false }, ]; function ASCIICheckbox({ isChecked }) { const check = isChecked ? "x" : " "; return ( <React.Fragment>[{check}]</React.Fragment> ); } function TodoList({ todos }) { return ( <ul> {todos.map((todo) => { <li key={todo.id}> <pre> <ASCIICheckbox isChecked={todo.isDone} /> {" "} {todo.task} </pre> </li> })} </ul> ); } function App() { return ( <div> <h1>My todo list:</h1> <TodoList todos={TODOS} /> </div> ); } ReactDOM.createRoot(document.querySelector("#root")).render(<React.StrictMode><App /></React.StrictMode>);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <div id="root"></div>
我期望渲染出3个任务,但实际并未显示。请问如何修复渲染逻辑,展示集合中的内容?
修复方案
问题出在map回调函数中:使用大括号{}包裹JSX时,没有显式返回该元素;箭头函数用大括号包裹代码块时,必须通过return语句返回值,否则默认返回undefined,导致<ul>没有子元素。
有两种修复方式:
方式1:添加显式return
function TodoList({ todos }) { return ( <ul> {todos.map((todo) => { // 添加return返回JSX元素 return ( <li key={todo.id}> <pre> <ASCIICheckbox isChecked={todo.isDone} /> {" "} {todo.task} </pre> </li> ); })} </ul> ); }
方式2:使用隐式返回
将大括号替换为小括号,让箭头函数隐式返回JSX元素(多行JSX建议用小括号包裹,避免语法错误):
function TodoList({ todos }) { return ( <ul> {todos.map((todo) => ( <li key={todo.id}> <pre> <ASCIICheckbox isChecked={todo.isDone} /> {" "} {todo.task} </pre> </li> ))} </ul> ); }
修复后,map会返回每个待办事项对应的<li>元素,<ul>即可正确渲染出3个任务项。
内容的提问来源于stack exchange,提问作者3limin4t0r
相关产品推荐
相关产品推荐

