React点击子组件修改父组件状态报错:map无法遍历state数组
问题原因与解决方案
1 核心错误排查
- useState使用错误:你没有调用
useState()钩子,直接对初始值数组解构,导致habits实际被赋值为数组的第一个元素(对象类型),对象本身没有map方法,才会出现无法遍历的报错。正确写法是把初始数组作为参数传入useState。 toggleCard逻辑错误:- 函数组件不存在
this,调用setHabits不需要加this前缀 - 切换状态需要先匹配到对应点击的条目id,且修改React state要遵循不可变原则,不能直接修改原对象属性,要返回全新的数组
- 函数组件不存在
- 组件导入导出命名不匹配:子组件导出名称是
Cards,父组件导入的是Card,会引发组件找不到的报错 - 子组件不需要重复写
key属性,key只需要在父组件遍历渲染子组件时声明即可
2 修正后代码
父组件CardStack.jsx
import React from "react"; import { useState } from "react"; // 修正导入名称和子组件导出名一致 import Cards from "./Card"; const CardStack = () => { // 修正useState调用写法 const [habits, setHabits] = useState([ { id: 1, merit: "good", title: "Good Habit", count: 4, text: "Words to be hidden", visible: false, }, { id: 2, merit: "bad", title: "Bad Habit", count: 1, text: "Words to be hidden", visible: false, }, { id: 3, merit: "good", title: "Good Habit", count: 6, text: "Words to be hidden", visible: true, }, ]); // 修正toggle逻辑,接收点击条目的id const toggleCard = (id) => { setHabits(prevHabits => prevHabits.map(habit => { // 匹配对应id的条目,修改visible属性,返回新对象 if(habit.id === id) { return {...habit, visible: !habit.visible} } // 其余条目原样返回 return habit })) }; return ( <div className="card-stack"> {habits.map((habit) => ( // 给点击事件传当前条目的id <Cards habit={habit} key={habit.id} onClick={() => toggleCard(habit.id)} /> ))} </div> ); }; export default CardStack;
子组件Cards.jsx
import React from "react"; //Components import Button from "./Button"; const Cards = ({ habit, onClick }) => { return ( // 删除子组件内部的key属性 <div className="card" onClick={onClick}> <h4 className="title" merit={habit.merit}> {habit.title} <div className="btn-group"> <Button className="button" /> <span className="count">{habit.count}</span> <Button className="button" /> </div> {habit.visible ? ( <div className="content"> <p>visible</p> </div> ) : null} </h4> </div> ); }; export default Cards;
3 疑问解答
- 你的实现思路是正确的,不需要额外新建数组遍历,修复上述错误后直接遍历state中的
habits数组即可正常运行。 - 类组件没有被弃用,目前React官方仍然完全支持类组件写法。不过现在官方推荐优先使用函数组件+Hook的写法开发新项目,学习阶段优先掌握函数组件即可,类组件可以作为扩展了解,遇到旧项目维护时再深入学习也没有问题。
内容的提问来源于stack exchange,提问作者Drew
相关产品推荐
相关产品推荐

