简体   繁体   English

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

[英]Re render child component depending on child action while passing data to parent in React

I have a Parent Component where I make an Ajax call to hydrate two children Components.我有一个父组件,我在其中进行了 Ajax 调用来水合两个子组件。 C1 only needs the data once, C2 actually is able to get more data through additional Ajax calls and will be re render adequately. C1 只需要一次数据,C2 实际上可以通过额外的 Ajax 调用获得更多数据,并且将被充分重新渲染。

It is way easier for me to make the Ajax Call in my Parent Component.在我的父组件中进行 Ajax 调用对我来说更容易。 But then I can't figure out how to 'get more data' in C2, pass that data in Parent and finally re render C2 only.但是后来我不知道如何在 C2 中“获取更多数据”,在 Parent 中传递该数据,最后只重新渲染 C2。 I had many tries through callbacks (you can see it in the code), lifting state up etc, I am unable to do it.我通过回调进行了很多尝试(您可以在代码中看到它),提升 state 等,我无法做到。 I don't know what to do with useEffect either...我也不知道用useEffect做什么......

Some code:一些代码:

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;

As you can see <ReviewsSideInfo/> (C1) relies on that Ajax call (using stats object), and so does <ReviewsContainer /> (C2), but in C2 ->:如您所见, <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>
    )
}

-> I need to be able to load more data. -> 我需要能够加载更多数据。 Sorry for the long piece of code.对不起,很长的一段代码。 How can I achieve that?我怎样才能做到这一点? I know useReducer may be of help but it seems even more difficult to me since I'm new to React.我知道 useReducer 可能会有所帮助,但对我来说似乎更加困难,因为我是 React 新手。

Last thing: in C1, I need to be able to filter that data (per rating) so I need to find a way to communicate through all these components... same problem actually.最后一件事:在 C1 中,我需要能够过滤该数据(按评级),因此我需要找到一种通过所有这些组件进行通信的方法……实际上是同样的问题。

EDIT : I could have updated the state in Parent component but then the whole component would refresh and that's not what I want (already tried that)编辑:我本可以更新父组件中的 state 但随后整个组件将刷新,这不是我想要的(已经尝试过)

Did you try wrapping your component with您是否尝试过用

React.memo(your component)

I will look something like below:我将如下所示:

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>

Also in也在

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

below useEffect will only be called when the offset and limit value is changed.下面的 useEffect 只会在偏移量和限制值改变时被调用。

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

below is how your state should look like:下面是您的 state 的外观:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM