如果用戶id輸入輸入,我想通過用戶輸入的特定 id 獲取帖子。如果沒有,我想獲取整個帖子陣列,然后從獲取的資料中獲取一些 id。我知道這沒有意義,但它只是為了測驗。
它不起作用,因為 useState 異步作業。我嘗試了幾個解決方案,但它們看起來都非常難看。
現場演示
我收到一個錯誤:
Cannot read properties of undefined (reading 'id')
原因setPosts還沒有確定。
處理這種情況的最佳、清晰的方法是什么?
import { useState } from "react";
export default function App() {
const [id, setId] = useState("");
const [post, setPost] = useState(null);
const [posts, setPosts] = useState([]);
const fetchPost = async (id) => {
const res = await axios.get(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
setPost(res.data);
};
const fetchPosts = async () => {
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
setPosts(res.data);
};
const onSubmit = async (e) => {
e.preventDefault();
if (id) {
await fetchPost(id);
} else {
await fetchPosts();
await fetchPost(posts[0].id);
}
};
return (
<div className="App">
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => setId(e.target.value)} />
<button type="submit">submit</button>
</form>
</div>
);
}
uj5u.com熱心網友回復:
您可以將 fetchPosts 視為副作用并包裝fetchPost(posts[0].id)在useEffect依賴項中posts。
或者直接使用結果onSubmit()(假設你不需要posts別的東西)。
const fetchPosts = async () => {
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
// setPosts(res.data); // this state is transitory and not used directly by the render
return res.data;
};
const onSubmit = async (e) => {
e.preventDefault();
if (id) {
await fetchPost(id);
} else {
const posts = await fetchPosts(); // Only used as part of submit event?
await fetchPost(posts[0].id);
}
};
return (
<div className="App">
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => setId(e.target.value)} />
<button type="submit">submit</button>
</form>
<div>{(post && post.title) || "No post yet"}</div>
</div>
);
uj5u.com熱心網友回復:
就像你說的 useState異步作業一樣,如果你想在改變它之后做一些事情,你將不得不使用useEffect并將帖子設定為它的引數,現在只要帖子發生突變,你的函式就會運行并且陣列的第一個索引將被發送到fetchPost(id),
import axios from "axios";
import "./styles.css";
import { useEffect, useState } from "react";
export default function App() {
const [id, setId] = useState("");
const [post, setPost] = useState(null);
const [posts, setPosts] = useState([]);
useEffect(() => {
if (posts.length) {
fetchPost(posts[0].id);
}
}, [posts]);
const fetchPost = async (id) => {
console.log(`fetching ${id}`);
const res = await axios.get(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
console.log(res.data);
setPost(res.data);
};
const fetchPosts = async () => {
console.log(`fetching all posts`);
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
setPosts(res.data);
};
const onSubmit = async (e) => {
e.preventDefault();
if (id) {
await fetchPost(id);
} else {
await fetchPosts();
// res = await fetchPost(posts[0].id); we dont need it here it defined in useffect function
}
};
const setDefaultId = (e) => {
setId(e.target.value);
};
return (
<div className="App">
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => setDefaultId(e)} />
<button type="submit">submit</button>
</form>
</div>
);
}
還要考慮永遠不要在回傳函式中直接更新狀態,這會導致性能問題
uj5u.com熱心網友回復:
問題出在“fetchPost”方法中。在此方法中,您有兩個具有相同名稱的變數。“id”來自狀態鉤子,“id”來自函式引數。您可以解決更改這些變數名稱之一的問題。
還有一件事,如果“id”沒有價值,那么你獲取第一篇文章的方式將無法正常作業,因為 await 方法不會等待狀態的變化。
我已經編輯了一些代碼來解決這兩個問題。
import { useState } from 'react';
import axios from 'axios';
export default function App() {
const [id, setId] = useState('');
const [post, setPost] = useState(null);
const fetchPost = async (idProp) => {
const res = await axios.get(
`https://jsonplaceholder.typicode.com/posts/${idProp}`,
);
setPost(res.data);
};
const fetchPosts = async () => {
const res = await axios.get('https://jsonplaceholder.typicode.com/posts');
await fetchPost(res.data[0].id);
};
const onSubmit = async (e) => {
e.preventDefault();
if (id) {
await fetchPost(id);
} else {
await fetchPosts();
}
};
return (
<div className="App">
<form onSubmit={onSubmit}>
<input type="text" onChange={(e) => {
setId(e.target.value);
}} />
<button type="submit">submit</button>
</form>
</div>
);
}
我希望我幫助了你。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/432120.html
標籤:javascript 反应 异步等待 反应钩子
