尽管我传递了第二个参数,但 React Hook useEffect() 运行 不断

React Hook useEffect() run continuously although I pass the second params

我对这段代码有疑问

如果我将整个pagination对象传递给useEffect()函数的第二个参数,那么fetchData()将连续调用。如果我只传递 pagination.current_page 那么它只会调用一次,但是当我设置新的 pagination 时,正如您在 navigatePage() 函数中看到的那样,useEffect() 不会调用 fetchData() 尽管 pagination 已更改。

如何解决这个问题。非常感谢!

此外,我不想在第一次安装组件时使用 useEffect() 调用,因为 items 是从 props 接收的(它是由服务器获取的,这是 nextjs 项目)。

import React, {useEffect, useState} from 'react';
import Filter from "../Filter/Filter";
import AdsListingItem from "../AdsListingItem/AdsListingItem";
import {Pagination} from "antd-mobile";

import styles from './AdsListing.module.css';

import axios from 'axios';

const locale = {
    prevText: 'Trang trước',
    nextText: 'Trang sau'
};

const AdsListing = ({items, meta}) => {

    const [data, setData] = useState(items);

    const [pagination, setPagination] = useState(meta);

    const {last_page, current_page} = pagination;

    const fetchData = async (params = {}) => {
        axios.get('/ads', {...params})
            .then(({data}) => {
                setData(data.data);
                setPagination(data.meta);
            })
            .catch(error => console.log(error))
    };

    useEffect( () => {
        fetchData({page: pagination.current_page});
    }, [pagination.current_page]);

    const navigatePage = (pager) => {
        const newPagination = pagination;
        newPagination.current_page = pager;
        setPagination(newPagination);
    };

    return (
        <>
            <Filter/>
            <div className="row  no-gutters">
                <div className="col-md-8">
                    <div>
                        {data.map(item => (
                            <AdsListingItem key={item.id} item={item}/>
                        ))}
                    </div>
                    <div className={styles.pagination__container}>
                        <Pagination onChange={navigatePage} total={last_page} current={current_page} locale={locale}/>
                    </div>
                </div>
                <div className="col-md-4" style={{padding: '15px'}}>
                    <img style={{width: '100%'}} src="https://tpc.googlesyndication.com/simgad/10559698493288182074"
                         alt="ads"/>
                </div>
            </div>


        </>
    )
};

export default AdsListing;

问题是您没有返回 new 对象引用。您保存对最后一个状态对象的引用,对其进行变异 属性,然后再次保存。

const navigatePage = (pager) => {
  const newPagination = pagination; // copy ref pointing to pagination
  newPagination.current_page = pager; // mutate property on ref
  setPagination(newPagination); // save ref still pointing to pagination
};

在这种情况下,在内存中的位置 pagination 保持不变。您应该将所有 pagination 属性 复制到 一个新对象中。

const navigatePage = (pager) => {
  const newPagination = {...pagination}; // shallow copy into new object
  newPagination.current_page = pager;
  setPagination(newPagination); // save new object
};

更进一步,您确实应该进行功能更新,以便正确排队更新。这是在单个渲染周期中多次调用 setPagination 的情况。

const navigatePage = (pager) => {
  setPagination(prevPagination => {
    const newPagination = {...prevPagination};
    newPagination.current_page = pager;
  });
};

在分页排队更新的情况下可能不是问题(最后一个当前页面集赢得下一次渲染战斗),但如果任何状态更新实际上 取决于先前的值然后肯定使用功能更新模式,