React Typescript.将新对象从api推送到包含现有对象的数组而不重复它们的正确方法 &



我有一个自定义钩子,我调用16个subreddits在时间,因为我想实现无限滚动。当url页面参数改变时,我想将新数据添加到数组中,然后我映射。但是我找不到正确的打字方式。你们谁能给我指路吗?

类型:

export type Subreddits = [Subreddit];
export type Subreddit = {
id: string;
title: string;
description: string;
}; 

钩:

function useSubreddit() {
let [subredditData, setSubredditData] = useState<any>([]);
const [loadingSubbredits, setLoadingSubreddits] = useState(false);
const [subredditError, setSubredditError] = useState(null);
const dispatch = useDispatch();
const url =
"https://6040c786f34cf600173c8cb7.mockapi.io/subreddits?page=1&limit=16";
useEffect(() => {
setLoadingSubreddits(true);
axios
.get(url)
.then((response) => {
setSubredditData(
(subredditData = [ new Set([...subredditData, ...response.data])])
);
dispatch(setSubredditsData(response.data));
})
.catch((err) => {
setSubredditError(err);
})
.finally(() => setLoadingSubreddits(false));
}, [url]);
return { loadingSubbredits, subredditError, subredditData };
}
export default useSubreddit;

这是向set添加新项的正确方法:

setSubredditData((
{ subredditData }) => ({
subredditData: new Set(subredditData).add(response.data)
})
);

subredditData类型更改为Array

const [subredditData, setSubredditData] = useState<Array>([])

然后使用;

setSubredditData(subredditData => [...subredditData, ...response.data])

理想情况下,你应该定义响应对象的类型,以便Typescript知道它拥有什么样的数据;

.then((response: ResponseType) => {

工作示例:codesandbox

import { useState, useEffect } from "react";
import axios from "axios";
function useSubreddit() {
let [subredditData, setSubredditData] = useState({});
const [loadingSubbredits, setLoadingSubreddits] = useState(false);
const [subredditError, setSubredditError] = useState(null);
//console.log(subredditData);
const url =
"https://6040c786f34cf600173c8cb7.mockapi.io/subreddits?page=1&limit=16";
useEffect(() => { 
setLoadingSubreddits(true);
axios
.get(url)
.then((response) => {
const result = response.data?.reduce((prev,curr) => ({ ...prev, ...{ [curr.id]: curr }}),{});

setSubredditData((subredditData) => ({ ...subredditData, ...result }));
})
.catch((err) => {
setSubredditError(err);
})
.finally(() => setLoadingSubreddits(false));
}, [url]);
return { loadingSubbredits, subredditError, subredditData:Object.values(subredditData) };
}
export default useSubreddit;

工作示例:https://codesandbox.io/s/musing-brown-9nf7ne?file=/src/App.js

我找到了解决方案

function useSubreddit() {
const [subredditData, setSubredditData] = useState<Array<any>>([])
const [loadingSubbredits, setLoadingSubreddits] = useState(false);
const [subredditError, setSubredditError] = useState(null);
const dispatch = useDispatch();
const url =
"https://6040c786f34cf600173c8cb7.mockapi.io/subreddits?page=1&limit=4";
useEffect(() => {
setLoadingSubreddits(true);
axios
.get(url)
.then((response: SubredditsResponse) => {
setSubredditData(Array.from( new Set([ ...subredditData, ...response.data])))
dispatch(setSubredditsData(response.data));
})
.catch((err) => {
setSubredditError(err);
})
.finally(() => setLoadingSubreddits(false));
}, [url]);
return { loadingSubbredits, subredditError, subredditData };
}
export default useSubreddit;

谢谢大家的帮助

最新更新