在 React 中将数据传递给父组件时,根据子操作重新渲染子组件

时间:2021-02-25 18:33:56

标签: javascript reactjs

我有一个父组件,我在其中进行了 Ajax 调用来水合两个子组件。 C1 只需要一次数据,C2 实际上可以通过额外的 Ajax 调用获得更多的数据,并且会被充分地重新渲染。

在我的父组件中进行 Ajax 调用要容易得多。但是后来我无法弄清楚如何在 C2 中“获取更多数据”,在 Parent 中传递该数据并最终仅重新渲染 C2。我通过回调(您可以在代码中看到它),提升状态等进行了多次尝试,但我无法做到。我也不知道要怎么处理 useEffect...

一些代码:

const Reviews: FunctionComponent = () => { 
    let variables = {
        offset: 0,
        limit: 2,
        filter: filter,
        order: order
    }

    useEffect(() => {
        console.log("useEffect called");
    });

    const {data: dataReviews, loading: loadingReviews, error: errorReviews} = useQuery(GetReviews, {
        ssr: false,
        variables: variables
    });

    function parentCallback(offset: number, limit: number) {
        variables.offset = offset;
        variables.limit = limit;
    }

    if (!loadingReviews && !errorReviews && dataReviews) {
        let reviews = !loadingReviews && !errorReviews && dataReviews ? dataReviews.reviews[0] : null;
        const stats = reviews.stats;

        reviews = reviews.reviews;

        return (
            <div className={`${styles.netreviews_review_rate_and_stars}`}>
                <ReviewsSideInfo stats={stats}
                                 total={getRecommandation(stats).total}
                                 recommandation={getRecommandation(stats).percentageRecommandation}
                />
                <ReviewsContainer parentCallback={parentCallback} reviews={reviews}/>
            </div>
        );
    }
    return (<div></div>);
}
export default Reviews;

如您所见,<ReviewsSideInfo/> (C1) 依赖于该 Ajax 调用(使用 stats 对象),<ReviewsContainer /> (C2) 也是如此,但在 C2 中 -> :

const ReviewsContainer: FunctionComponent<ReviewsContainerProps> = ({reviews, parentCallback}) => {
    const [{offset, limit}, setReviews] = useState({offset: 0, limit: 3});
        
    return (
        <div className={`${styles.right_block}`}>
            <div className={`${styles.reviews_list}`}>

                <Fragment>
                    {reviews.map((element, i) => {
                        return (
                            <div>
                                <div key={i}>
                                    <Review rate={element.rate}
                                            firstname={element.firstname}
                                            lastname={element.lastname}
                                            review={element.review}
                                     />
                                </div>
                            </div>
                        )
                    })}
                    <button onClick={() => {
                        setReviews({offset: 0, limit: limit + 3});
                        parentCallback(0, limit + 3)
                    }}>
                        <FormattedMessage id="load-more"/></button>
                </Fragment>
            </div>
        </div>
    )
}

-> 我需要能够加载更多数据。 抱歉,代码很长。我怎样才能做到这一点?我知道 useReducer 可能会有所帮助,但对我来说似乎更难,因为我是 React 的新手。

最后一件事:在 C1 中,我需要能够过滤该数据(按评分),因此我需要找到一种通过所有这些组件进行通信的方法......实际上是同样的问题。< /p>

编辑:我本可以更新父组件中的状态,但随后整个组件都会刷新,这不是我想要的(已经尝试过)

1 个答案:

答案 0 :(得分:1)

你有没有尝试用

包裹你的组件
React.memo(your component)

我会看起来像下面这样:

const MemoisedComponent = React.memo(ReviewsSideInfo);




<div className={`${styles.netreviews_review_rate_and_stars}`}>
                <MemoisedComponent stats={stats}
                                 total={getRecommandation(stats).total}
                                 recommandation={getRecommandation(stats).percentageRecommandation}
                />
                <ReviewsContainer parentCallback={parentCallback} reviews={reviews}/>
            </div>

也在

parentCallback(offset,limit) {
setOffset(offset)
setLimit(limit)
}

下面的 useEffect 只会在偏移量和限制值改变时调用。

useEffect(() => {
//api call logic 
},[offset,limit]);

下面是你的状态应该是什么样子:

const [offset,setOffset] = useState(0)
const [limit,setLimit] = useState(3)
...and so on