你們能幫我做一個基本的 React 應用嗎:) 我想讀一個 json 檔案:
[
{
"name": "Google",
"url": "www.google.com",
"status": "to evaluate"
},
{
"name": "Bing",
"url": "www.bing.com",
"status": "to evaluate"
},
etc.
]
在閱讀它時,我想獲取 url 來填充這個 json 檔案中的狀態
最后,我只想制作一個有兩列的表:第一列是帶有 url 的名稱,第二列是狀態
我試過了,但它不起作用:O
import React, { useState } from 'react'
import Table from 'react-bootstrap/Table'
import jsonData from './data/urls.json'
function ListUrls () {
const [jsonArray, setJsonArray] = useState(jsonData)
async function fetchData (array) {
try {
array.map (url => {
const response = await fetch(url.url)
setJsonArray(url.status = response.status)
})
} catch (error) {
console.log('Error', error);
}
fetchData(jsonArray)
return (
<div>
<Table>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{jsonArray.map(url => (
<tr>
<td>
<a href={url.url} target='_blank'}>
{url.name}
</a>
</td>
<td>
{url.status}
</td>
</tr>
))}
</tbody>
</Table>
</div>
)
}
export default ListUrls
順便說一句,我真的很想用鉤子來做:)
所以,我除了看這張表,但頁面是空白的:/

uj5u.com熱心網友回復:
正如其他人所指出的,您將需要useEffect在這種情況下使用。否則fetchData,每次更新狀態時都會一遍又一遍地呼叫你。我還將更改您呼叫這些 URL 以獲取其 http 狀態的方式以使用承諾(只是因為我喜歡承諾)。以下是我將如何撰寫您的代碼:
import { useEffect, useState } from "react";
import "./styles.css";
import jsonData from "./urls.json";
export default function App() {
const [data, setData] = useState(jsonData);
useEffect(() => {
const promises = jsonData.map((url, i) => {
return fetch(url.url).then((r) => ({ fetch: r, index: i }));
});
Promise.all(promises)
.then((result) => {
const new_data = result.map((d) => {
jsonData[d.index].status = d.fetch.status;
return jsonData[d.index];
});
setData(new_data);
})
.catch((e) => {
console.log("Handle error here");
});
}, []);
return (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{data.map((url, i) => (
<tr key={i}>
<td>
<a href={url.url} target={"_blank"}>
{url.name}
</a>
</td>
<td>{url.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
請注意,我使用的是常規<table>元素而不是您的預建元素<Table>,因為我沒有它。這是一個沙箱:https ://codesandbox.io/s/confident-jang-yrxv3?file=/src/App.js:285-286
fetch回傳一個 Promise,當它被決議時,會產生 fetch 回應物件。因此,如果您只有一個 fetch 要做,您可以這樣稱呼它:
fetch(url).then(response => {//do stuff here with response object})
But let's say you have multiple fetch commands as you do in your case. How do you resolve them with just one then. Well that's where Promise.all() comes in handy. The idea is to get all the promises from your fetch commands and then resolve them all in one shot. As such:
const promises = jsonData.map((url, i) => {
return fetch(url.url).then((r) => ({ fetch: r, index: i }));
});
promises will be an array of promises that all the fetch commands inside the map return. One caveat here is I also return the index of the specific URL so that later you can use it to see which URL corresponds to which HTTP code. And finally you resolve them all using:
Promise.all(promises)
.then((result) => {
...
...
Simple right?
uj5u.com熱心網友回復:
您應該將 jsonArray 更改為 jsonData 作為引數,并將初始狀態設定為 null。
目前,您在呼叫函式時傳入狀態 (jsonArray) 而不是 jsonData。此外,您應該將 fetchData 的呼叫放在使用 jsonData 作為引數的 useEffect 中:
useEffect(() => fetchData(jsonData), [jsonData, fetchData]);
uj5u.com熱心網友回復:
這會變成一個回圈嗎?組件加載 ->fetchData()被呼叫 ->fetchData()更新狀態 -> 組件重新加載 -> 重復。
您可以使用useEffect()帶有空陣列的鉤子作為第二個引數只運行一次:
useEffect(() => {
//Update json as you were doing;
}, []);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/422876.html
標籤:
