[英]React - Updating previous array with new values using useState hook
我创建了一个包含三个组件HomeHeader
、 CompanyList
和ScrollToTopBtn
的主页。 专注于CompanyList
,它是一个容器组件,显示在Home
中使用 API 获取的CompanyCards
列表。 公司列表在Home
中像这样初始化
const [companies, setCompanies] = useState([]);
问题是最初在拨打 API 之后,我使用 spread operator 像这样更新companies
列表
const fetchedCompanies = await fetchFeedData(page);
console.log(fetchedCompanies);
setCompanies((prevCompanies=>{return [...prevCompanies,fetchedCompanies]}));
console.log(companies);
但是发生错误Uncaught TypeError: prevCompanies is not iterable
因为我相信companies
列表最初是空的。
我尝试通过使用concat
方法来使用另一种方法,但是companies
列表保持为空并且no companies found
的消息。
下面是Home
的源代码
const Home = () => {
const [page, setPage] = useState(1); //In order to avoid showing "no companies found" initially
const [isLoading, setIsLoading] = useState(true);
const [companies, setCompanies] = useState([]);
const [isError, setIsError] = useState(false);
const [hasMore, setHasMore] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
setIsError(false);
try {
const fetchedCompanies = await fetchFeedData(page);
setCompanies((prevCompanies=>{prevCompanies.concat(fetchedCompanies)})); //problem here
setHasMore(fetchedCompanies.length > 0)
} catch (e) {
setIsError(true)
setHasMore(false);
}
setIsLoading(false)
}
fetchData();
}, [page])
return (
<div>
<ScrollToTopBtn />
<Helmet>
<title>{stackinfo.title} - {home.title}</title>
</Helmet>
<HomeHeader />
{
isLoading ? (<LoadingSpinner />) :
isError ? (<ErrorBoundary message={somethingWrongError.message}></ErrorBoundary>) :
<CompanyList companies={companies} ></CompanyList>
}
<Container className={"mt-5"}>
<Row>
<Col sm={12}>
{(!isLoading && !isError && hasMore) &&
<CustomBtn
ButtonText={showMoreBtnText.message}
onClick={() => { console.log("Need to increment number of pages") }}
></CustomBtn>}
</Col>
</Row>
</Container>
</div>
)
}
在拨打 API 电话后,我试图检查fetchedCompanies
和companies
const fetchedCompanies = await fetchFeedData(page);
//Returning new array containing previous companies and recent fetchedCompanies
console.log(fetchedCompanies);
setCompanies((prevCompanies=>{prevCompanies.concat(fetchedCompanies)}));
console.log(companies);
fetchedCompanies
记录了一个包含 9 个元素的数组,而上面提到的companies
记录了空数组[]
。
对不起,如果我错过了什么,我对 React 还是个新手。
您可以在下面执行此操作以更新
setCompanies([...companies, ...fetchedCompanies])
如果获取的公司是全新的数组,包含所有以前的记录,那么就在下面做;
setCompanies([...fetchedCompanies]);
//OR
setCompanies(fetchedCompanies);
如果您有空字符串,请在下面执行此操作
setCompanies([...companies, ...fetchedCompanies.filter(com => !com)]);
这是试图改变 state,而不是返回一个新的 state(或者你可能只是忘记了return
关键字?):
setCompanies((prevCompanies=>{prevCompanies.concat(fetchedCompanies)}));
您之前的尝试更接近:
setCompanies(prevCompanies=>{return [...prevCompanies, fetchedCompanies]});
但是,如果fetchedCompanies
也是一个数组,那么您就忘记了它的扩展运算符:
setCompanies(prevCompanies=>{return [...prevCompanies, ...fetchedCompanies]});
如果没有它,结果数组充其量只会很奇怪。
你也可以稍微简化一下:
setCompanies(prevCompanies=>[...prevCompanies, ...fetchedCompanies]);
如果您不希望这些调用完全重叠,您可能会简化很多:
setCompanies([...companies, ...fetchedCompanies]);
如果在那之后仍然有一个空字符串,那么数据似乎是一个空字符串。 在那种情况下,您必须手动过滤掉它,如果过滤行为可能会与您那里的逻辑 rest(例如, hasMore
值)混淆,那么您在哪里进行过滤实际上取决于您。 但是您可以随时将 append .filter()
转换为结果数组。 获取时,更新 state 时,甚至只是渲染时。
您最好查看空字符串的来源并尝试解决该问题,但如果您只是想删除空字符串,请使用以下命令。
prevCompanies.concat(fetchedCompanies).filter(Boolean)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.