尽管我传递了第二个参数,但 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;
});
};
在分页排队更新的情况下可能不是问题(最后一个当前页面集赢得下一次渲染战斗),但如果任何状态更新实际上 取决于先前的值然后肯定使用功能更新模式,
我对这段代码有疑问
如果我将整个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;
});
};
在分页排队更新的情况下可能不是问题(最后一个当前页面集赢得下一次渲染战斗),但如果任何状态更新实际上 取决于先前的值然后肯定使用功能更新模式,