ReactJS对象数组类型错误及父子组件数据传递问题
React父子组件类型错误与数据传递异常解决方案
问题1:类型错误修复
错误原因
父组件addLesson方法接收Lesson[]类型参数,调用setLessons([...lessons, lesson])时,相当于把一个Lesson[]塞进了Lesson[]数组,导致最终类型变成(Lesson | Lesson[])[],与定义的Lesson[]类型不匹配,触发TS类型报错。
修正方案
调整父组件的addLesson参数类型为单个Lesson,同时修改setLessons的更新逻辑:
import React, { useState, useEffect } from 'react' import { Lesson } from './LessonType' import NewLessonModal from './NewLesson'; function LessonList() { const [lessons, setLessons] = useState<Lesson[]>([]); const url = "https://localhost:7065/api/Lessons" // 修改参数为单个Lesson类型 const addLesson = (lesson: Lesson) => { // 将单个Lesson添加到数组中 setLessons([...lessons, lesson]) console.log(lesson) } return ( <div> <NewLessonModal addLesson={addLesson} /> </div> ) }
问题2:子组件数据传递异常修复
错误原因
- 子组件中
setLessonData是异步更新状态的,调用setLessonData后立刻访问lessonData拿到的是更新前的旧值,导致首次传递数据为空。 - 子组件无需维护
lessonData状态,直接将新创建的Lesson对象传递给父组件即可。
修正方案
删除子组件的lessonData状态,直接在addNewLesson中构造Lesson对象并传递给父组件:
import { ChangeEvent, useState } from "react"; import { Lesson } from './LessonType' // 修改Props的addLesson参数为单个Lesson类型 type Props = { addLesson(lessonData: Lesson): void } function NewLessonModal({ addLesson }: Props) { const [name, setname] = useState<string>("") const [notes, setnotes] = useState<string>("") const [startDate, setstartDate] = useState<string>("") const [endDate, setendDate] = useState<string>("") const [hour, sethour] = useState<number>(0) const [certificate, setcertificate] = useState<string>("") const [imagePath, setimagePath] = useState<string>("") const changeValue = (event: ChangeEvent<HTMLInputElement>) => { if (event.target.name === "name") { setname(event.target.value) } if (event.target.name === "notes") { setnotes(event.target.value) } if (event.target.name === "startDate") { setstartDate(event.target.value) } if (event.target.name === "endDate") { setendDate(event.target.value) } if (event.target.name === "hour") { sethour(Number(event.target.value)) } } const addNewLesson = () => { // 直接构造新的Lesson对象 const newLesson: Lesson = { name: name, note: notes, startDate: startDate, endDate: endDate, hour: hour, certificate: certificate, imagePath: imagePath } // 直接传递给父组件 addLesson(newLesson) // 可选:清空表单输入 setname("") setnotes("") setstartDate("") setendDate("") sethour(0) setcertificate("") setimagePath("") } return ( {/* 你的表单JSX代码 */} <div> <input name="name" value={name} onChange={changeValue} /> {/* 其他表单元素 */} <button onClick={addNewLesson}>添加课程</button> </div> ) }
额外优化建议
- 父组件更新状态时,建议使用函数式更新,避免因闭包导致的状态不一致问题:
const addLesson = (lesson: Lesson) => { setLessons(prevLessons => [...prevLessons, lesson]) } - 子组件的
changeValue方法可以简化,避免多个if判断:const changeValue = (event: ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; switch(name) { case "hour": sethour(Number(value)); break; case "name": setname(value); break; case "notes": setnotes(value); break; case "startDate": setstartDate(value); break; case "endDate": setendDate(value); break; // 其他字段同理 } }
内容的提问来源于stack exchange,提问作者Utku ARSLAN
相关产品推荐
相关产品推荐

