React+TypeScript中如何将子组件的数组对象传递给父组件?
解决React子组件向父组件传递新增书籍数据的问题
核心问题是React组件间的状态传递逻辑——子组件无法直接修改父组件状态,必须通过父组件传递回调函数的方式实现数据向上传递。以下是具体修改方案:
1. 修改父组件(Booklists)
- 新增回调函数
handleAddBook,用于接收子组件传来的新书籍数据,并更新父组件的books状态 - 修复
useEffect的依赖问题(原依赖books会导致无限请求接口,改为空数组仅在组件挂载时请求一次) - 将回调函数作为props传给子组件
NewBookModal
修改后的父组件代码:
import { useState, useEffect } from "react"; import { IBook, NewBook } from './BookType' import BooklistItem from './BooklistItem' import NewBookModal from './NewBook'; function Booklists() { const [books, setBooks] = useState<IBook[]>([]); const url = "https://localhost:7065/api/BookRecommendation" const getData = () => { fetch(url) .then(res => res.json()) .then(res => { setBooks(res.data) }) } // 处理子组件传来的新书籍 const handleAddBook = (newBook: NewBook) => { // 转换类型:NewBook的image是可选,IBook是必填,这里给默认值(可根据需求调整) const bookToAdd: IBook = { ...newBook, image: newBook.image || "" // 也可设置默认占位图URL } // 将新书籍添加到现有列表 setBooks(prevBooks => [...prevBooks, bookToAdd]) } useEffect(() => { getData() }, []) // 改为空数组,仅组件挂载时请求一次 return ( <div> {/* 传递回调函数给子组件 */} <NewBookModal onAddBook={handleAddBook} /> <BooklistItem book={books} /> </div> ) } export default Booklists;
2. 修改子组件(NewBookModal)
- 移除子组件内部的
bookData状态(无需自行存储,父组件已统一维护书籍列表) - 定义props类型,接收父组件传来的
onAddBook回调函数 - 在
addNewBook函数中调用onAddBook,将新书籍数据传递给父组件
修改后的子组件代码:
import { ChangeEvent, useState } from "react"; import { NewBook } from './BookType' // 定义子组件的props类型 interface NewBookModalProps { onAddBook: (book: NewBook) => void; } function NewBookModal({ onAddBook }: NewBookModalProps) { const [title, setTitle] = useState<string>("") const [url, setUrl] = useState<string>("") const [description, setDescription] = useState<string>("") const [image, setImage] = useState<string>("") // 可选:如果需要用户输入图片链接 const changeValue = (event: ChangeEvent<HTMLInputElement>) => { const { name, value } = event.target; // 用switch优化多条件判断,更简洁 switch(name) { case "title": setTitle(value); break; case "url": setUrl(value); break; case "description": setDescription(value); break; case "image": setImage(value); break; default: break; } } const addNewBook = () => { // 构造新书籍对象 const newBook: NewBook = { title, url, description, image }; // 调用父组件的回调函数,传递数据 onAddBook(newBook); // 清空输入框 setTitle("") setUrl("") setDescription("") setImage("") } return ( // 模态框UI示例,可根据实际需求调整 <div> <input type="text" name="title" value={title} onChange={changeValue} placeholder="书名" /> <input type="text" name="url" value={url} onChange={changeValue} placeholder="书籍链接" /> <input type="text" name="description" value={description} onChange={changeValue} placeholder="书籍描述" /> <input type="text" name="image" value={image} onChange={changeValue} placeholder="图片链接(可选)" /> <button onClick={addNewBook}>添加书籍</button> </div> ) } export default NewBookModal;
关键改动说明
- 父子组件通信:通过父组件传递回调函数
onAddBook,子组件调用该函数实现数据向上传递,这是React单向数据流的标准实现方式 - 状态统一管理:书籍列表状态由父组件集中维护,子组件仅负责收集用户输入并通知父组件更新,避免状态分散
- 类型兼容处理:针对
NewBook和IBook的类型差异,补充必填字段的默认值,确保数据能正确存入父组件状态 - 性能优化:修复
useEffect的依赖问题,避免无限重复请求接口
内容的提问来源于stack exchange,提问作者Utku ARSLAN
相关产品推荐
相关产品推荐

