温馨提示:本文翻译自stackoverflow.com,查看原文请点击:reactjs - React Hook useEffect() run continuously although I pass the second params
reactjs react-hooks use-effect

reactjs - 尽管我通过了第二个参数,但是React Hook useEffect()连续运行

发布于 2020-03-27 15:42:47

我有这个代码的问题

如果我将整个pagination对象传递useEffect()函数的第二个参数fetchData()则将连续调用。如果我只通过pagination.current_page它,它将仅调用一次,但是当我paginationnavigatePage()函数中看到新设置的值时,尽管发生了变化useEffect()但不调用fetchData()pagination

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

此外,我不希望useEffect()在首次安装组件时使用use 调用,因为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;

查看更多

查看更多

提问者
Jeffrey K
被浏览
48
Drew Reese 2020-01-31 16:14

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

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;
  });
};

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