使用多个 React useState() 挂钩从 json api 获取类别标题和帖子
Use multiple React useState() hooks to fetch Category title and posts from json api
我正在使用 React useState() 和 useEffect 从 api (mock-data/my-data.json
).
中获取多个数据
从 api 我想获取 类别标题 和 帖子列表 并在 jsx
.
这是使用 useState()
和 useEffect()
获取数据的正确方法吗?我制作了多个 useState 常量,所以在我可以在渲染方法中渲染 Title 和列表操作 Posts 之后:
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('')
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
axios
.get('mock-data/my-data.json')
.then(res => {
console.log(res.data)
setCategoryTitle(res.data['title'])
setPosts(res.data.allItems)
setLoading(false)
})
.catch(err => {
console.log(err)
})
}, [])
if (loading) {
return <p>Loading articles...</p>
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
)
}
是的,这是正确的方法。如果你只想使用一个 useState,你可以克隆状态对象。
例如:
const [state, setState] = useState({
title: "",
posts: []
});
// For Title
setState({...state, title: "New Title"})
// For Posts
setState({...state, posts: [{...post...}]}
但我想使用 lodash 克隆、immer 库或类似的东西。
我觉得不错。
如果我要重构此代码,我更愿意使用 async/await,并且我喜欢使用状态枚举而不是布尔值,用于 loading/loaded/error 个状态。
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('');
const [posts, setPosts] = useState([]);
const [state, setState] = useState('loading');
useEffect(() => {
const fetchPosts = async () => {
setState('loading');
let response = axios.get('mock-data/my-data.json');
try {
response = await response;
} catch (error) {
setState('error');
return;
}
setCategoryTitle(response.data['title']);
setPosts(response.data.allItems);
setState('loaded');
};
fetchPosts();
}, []);
if (state === 'loading') {
return <p>Loading articles...</p>;
}
if (state === 'error') {
return <p>Error loading articles...</p>;
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
);
}
差不多就这些了,我唯一强烈推荐的是使用 await 而不是著名的 hadoukens/pyramids of doom,所以一个简单的代码是:
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('')
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(false)
useEffect(() => {
async function getData(){
try{
setLoading(true)
res = await axios.get('mock-data/my-data.json');
console.log(res.data)
setCategoryTitle(res.data['title'])
setPosts(res.data.allItems)
setLoading(false)
}catch(err){
console.log(err)
}
}
getData();
}, [])
if (loading) {
return <p>Loading articles...</p>
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
)
}
如果您想同时设置多个状态,通常使用 useReducer
钩子而不是使用多个 useState
钩子是个好主意。您的示例是您尝试将多个状态设置在一起的情况。
useReducer
使用 reducer 函数,其中可以操纵合并状态。在我看来,这使代码更具凝聚力和可读性。
请参阅下面的示例代码。为简单起见,我删除了 axios,但你应该明白了。
https://codesandbox.io/s/bold-platform-hv6pi?file=/src/ArticleList.js
我正在使用 React useState() 和 useEffect 从 api (mock-data/my-data.json
).
从 api 我想获取 类别标题 和 帖子列表 并在 jsx
.
这是使用 useState()
和 useEffect()
获取数据的正确方法吗?我制作了多个 useState 常量,所以在我可以在渲染方法中渲染 Title 和列表操作 Posts 之后:
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('')
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
axios
.get('mock-data/my-data.json')
.then(res => {
console.log(res.data)
setCategoryTitle(res.data['title'])
setPosts(res.data.allItems)
setLoading(false)
})
.catch(err => {
console.log(err)
})
}, [])
if (loading) {
return <p>Loading articles...</p>
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
)
}
是的,这是正确的方法。如果你只想使用一个 useState,你可以克隆状态对象。 例如:
const [state, setState] = useState({
title: "",
posts: []
});
// For Title
setState({...state, title: "New Title"})
// For Posts
setState({...state, posts: [{...post...}]}
但我想使用 lodash 克隆、immer 库或类似的东西。
我觉得不错。
如果我要重构此代码,我更愿意使用 async/await,并且我喜欢使用状态枚举而不是布尔值,用于 loading/loaded/error 个状态。
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('');
const [posts, setPosts] = useState([]);
const [state, setState] = useState('loading');
useEffect(() => {
const fetchPosts = async () => {
setState('loading');
let response = axios.get('mock-data/my-data.json');
try {
response = await response;
} catch (error) {
setState('error');
return;
}
setCategoryTitle(response.data['title']);
setPosts(response.data.allItems);
setState('loaded');
};
fetchPosts();
}, []);
if (state === 'loading') {
return <p>Loading articles...</p>;
}
if (state === 'error') {
return <p>Error loading articles...</p>;
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
);
}
差不多就这些了,我唯一强烈推荐的是使用 await 而不是著名的 hadoukens/pyramids of doom,所以一个简单的代码是:
function ArticleList() {
const [categoryTitle, setCategoryTitle] = useState('')
const [posts, setPosts] = useState([])
const [loading, setLoading] = useState(false)
useEffect(() => {
async function getData(){
try{
setLoading(true)
res = await axios.get('mock-data/my-data.json');
console.log(res.data)
setCategoryTitle(res.data['title'])
setPosts(res.data.allItems)
setLoading(false)
}catch(err){
console.log(err)
}
}
getData();
}, [])
if (loading) {
return <p>Loading articles...</p>
}
return (
<div>
<h1>{categoryTitle}</h1>
<ul>
{posts.map(post => (
<li key={post.id}>{post.titel}</li>
))}
</ul>
</div>
)
}
如果您想同时设置多个状态,通常使用 useReducer
钩子而不是使用多个 useState
钩子是个好主意。您的示例是您尝试将多个状态设置在一起的情况。
useReducer
使用 reducer 函数,其中可以操纵合并状态。在我看来,这使代码更具凝聚力和可读性。
请参阅下面的示例代码。为简单起见,我删除了 axios,但你应该明白了。
https://codesandbox.io/s/bold-platform-hv6pi?file=/src/ArticleList.js