数组的 setState 反应挂钩不保存先前的数组元素
setState react hook for array is not saving prior array elements
我有一个使用 aysnc 和 await 的 API 请求,抓取数据,然后使用 Promise.all 发出第二个请求,这会发出多个 API 带有 id 的请求。那部分效果很好。
但是,当我将数据保存在一个名为“setItem”的 React 钩子中时,它只保存了一个并覆盖了其他的。我在 setItem()
中有一个传播运算符
setItems(...项目, 数据)
数据是来自 API 请求的响应。
我的 API 请求在我的 React 应用程序的顶层,所以我将它拉到它自己的小帮助文件中,这就是为什么“items”和“setItems”是传递的参数。
import axios from 'axios';
import BottleNeck from 'bottleneck'
const limiter = new BottleNeck({
maxConcurrent: 1,
minTime: 333
})
export const Request = (items, setItems) => {
const getData = () => {
const options = 'newstories'
const API_URL = `https://hacker-news.firebaseio.com/v0/${options}.json?print=pretty`;
return new Promise((resolve, reject) => {
return resolve(axios.get(API_URL))
})
}
const getIdFromData = (dataId) => {
const API_URL = `https://hacker-news.firebaseio.com/v0/item/${dataId}.json?print=pretty`;
return new Promise((resolve, reject) => {
return resolve(axios.get(API_URL))
})
}
const runAsyncFunctions = async () => {
const {data} = await getData()
Promise.all(
data.map(async (d) => {
const {data} = await limiter.schedule(() => getIdFromData(d))
//****************** issue here ************************//
setItems([...items, data]);
})
)
}
runAsyncFunctions()
}
以防万一您想查看 app.js 文件以供参考
import React, { useState, useEffect } from 'react';
import './App.css';
import { SearchBar } from './search-bar';
import { Results } from './results';
import { Request } from './helper/request'
function App() {
const [input, setInput] = useState('');
const [items, setItems] = useState([]);
const handleChange = val => {
setInput(val)
}
// console.log(input)
// console.log(results)
// API calls
// call useEffect here, calls Request(), put results in useEffect
useEffect(() => {
Request(items, setItems)
}, [])
return (
<div className="App">
<SearchBar handleChange={handleChange}/>
<Results items={items} />
</div>
);
}
export default App;
在您的 Promise.all
return 每个数据处,在您可以与 then
链接之后传递一个包含所有已解析数据的数组。这样你只需要调用一次setItems
:
Promise.all(
data.map(async (d) => {
const { data } = await limiter.schedule(() => getIdFromData(d));
return data;
})
).then((dataResults) => setItems((results) => [...results, ...dataResults]));
我有一个使用 aysnc 和 await 的 API 请求,抓取数据,然后使用 Promise.all 发出第二个请求,这会发出多个 API 带有 id 的请求。那部分效果很好。
但是,当我将数据保存在一个名为“setItem”的 React 钩子中时,它只保存了一个并覆盖了其他的。我在 setItem()
中有一个传播运算符setItems(...项目, 数据)
数据是来自 API 请求的响应。
我的 API 请求在我的 React 应用程序的顶层,所以我将它拉到它自己的小帮助文件中,这就是为什么“items”和“setItems”是传递的参数。
import axios from 'axios';
import BottleNeck from 'bottleneck'
const limiter = new BottleNeck({
maxConcurrent: 1,
minTime: 333
})
export const Request = (items, setItems) => {
const getData = () => {
const options = 'newstories'
const API_URL = `https://hacker-news.firebaseio.com/v0/${options}.json?print=pretty`;
return new Promise((resolve, reject) => {
return resolve(axios.get(API_URL))
})
}
const getIdFromData = (dataId) => {
const API_URL = `https://hacker-news.firebaseio.com/v0/item/${dataId}.json?print=pretty`;
return new Promise((resolve, reject) => {
return resolve(axios.get(API_URL))
})
}
const runAsyncFunctions = async () => {
const {data} = await getData()
Promise.all(
data.map(async (d) => {
const {data} = await limiter.schedule(() => getIdFromData(d))
//****************** issue here ************************//
setItems([...items, data]);
})
)
}
runAsyncFunctions()
}
以防万一您想查看 app.js 文件以供参考
import React, { useState, useEffect } from 'react';
import './App.css';
import { SearchBar } from './search-bar';
import { Results } from './results';
import { Request } from './helper/request'
function App() {
const [input, setInput] = useState('');
const [items, setItems] = useState([]);
const handleChange = val => {
setInput(val)
}
// console.log(input)
// console.log(results)
// API calls
// call useEffect here, calls Request(), put results in useEffect
useEffect(() => {
Request(items, setItems)
}, [])
return (
<div className="App">
<SearchBar handleChange={handleChange}/>
<Results items={items} />
</div>
);
}
export default App;
在您的 Promise.all
return 每个数据处,在您可以与 then
链接之后传递一个包含所有已解析数据的数组。这样你只需要调用一次setItems
:
Promise.all(
data.map(async (d) => {
const { data } = await limiter.schedule(() => getIdFromData(d));
return data;
})
).then((dataResults) => setItems((results) => [...results, ...dataResults]));