React中如何在单组件渲染多来源props并传递给子组件
问题核心原因
首先你的代码存在两个需要修正的逻辑问题:
- App组件的异步请求逻辑有缺陷:批量发起的外部接口请求是异步执行的,你在循环内直接执行
setPostsExternal(externalPosts)时,大部分请求还没有返回结果,externalPosts数组是空的或者数据不全,也没法触发正确的状态更新。 - 数据没有配对:你直接把整个
postsExternal数组传给每个Post组件,自然没法拿到对应单条帖子的rating属性。
解决方案
第一步:修正App组件的请求逻辑
用Promise.all处理所有并发的外部帖子请求,等所有请求返回后再统一更新状态,保证两个数组的顺序一一对应:
import React, { useState, useEffect } from "react"; import axios from "axios"; import { Posts } from './components'; const App = () => { const [posts, setPosts] = useState([]); const [postsExternal, setPostsExternal] = useState([]); const fetchPostsAll = async () => { const { data: originPosts } = await axios.get(`http://localhost:2000/posts`); setPosts(originPosts); // 批量发起所有外部请求,等全部返回后再更新状态 const externalPromiseList = originPosts.map(({ external_id }) => axios.get(`http://localhost:2000/posts${external_id}`).then(res => res.data) ); const allExternalPosts = await Promise.all(externalPromiseList); setPostsExternal(allExternalPosts); } useEffect(() => { fetchPostsAll(); }, []); return ( <div> <Navbar/> <Posts posts={posts} postsExternal={postsExternal} /> </div> ); }; export default App;
第二步:修正Posts组件的映射逻辑
遍历的时候通过索引取对应位置的外部帖子数据,传给单个Post组件:
import React from 'react'; import Post from './Post/Post'; const Posts = ({ posts, postsExternal }) => { // 保证两个数组长度一致再渲染,避免索引错位 if (posts.length !== postsExternal.length) return <div>加载中...</div> return ( <main> <Container fluid> <Row className="p-2"> { posts.map((post, index) => ( <Col className="p-lg-4 p-sm-3" key={post.id} xs={6} sm={4} md={3} lg={3} xl={2}> <Post post={post} postExternal={postsExternal[index]} /> </Col> ))} </Row> </Container> </main> ); }; export default Posts;
你的Post组件不需要做修改就可以正常拿到postExternal.rating属性了。
更推荐的优化方案
你可以直接在App组件里就把原帖子和对应外部数据合并成一个数组,不需要单独传两个数组,后续维护更简单:
在App的fetchPostsAll里直接合并:
const [mergedPosts, setMergedPosts] = useState([]); // ...请求完成后 const merged = originPosts.map((post, index) => ({ ...post, external: allExternalPosts[index] })); setMergedPosts(merged);
之后直接把mergedPosts传给Posts组件遍历即可,不需要再做索引配对。
内容的提问来源于stack exchange,提问作者Yeshwanth B
相关产品推荐
相关产品推荐

