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

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:子组件数据传递异常修复

错误原因

  1. 子组件中setLessonData是异步更新状态的,调用setLessonData后立刻访问lessonData拿到的是更新前的旧值,导致首次传递数据为空。
  2. 子组件无需维护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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:17:01