我试图获取一个对象,并且获取,我在response.data中获取了正确的数据,但是我无法将其设置为state。它只是保留为空对象。我究竟做错了什么? Post是一个json对象,具有多个字段,例如:post_id,post_title,post_content等。
const [post, setPost] = useState({})
let id = match.params.id
useEffect(() => {
axios.get(`${BASE_URL}/post?id=${id}`)
.then(response => {
console.log(response.data)
setPost(response.data)
})
.then(() => {
console.log("post: ", post)
}
)
答案 0 :(得分:1)
Text("abdominal pain")
Text("abnormal menstruation")
Text("acidity")
Text("acute liver failure")
Text("altered sensorium")
Text("anxiety")
这样的setAction是异步的,如官方REACT文档(https://reactjs.org/docs/hooks-reference.html#usestate)所述;这意味着,一旦执行了setAction,您就不会知道它何时会真正执行和终止:您将知道,因为组件将重新呈现。
在您的情况下,如果您想在setPost
获得新值后执行操作,则需要使用post
钩子(https://reactjs.org/docs/hooks-reference.html#useeffect):
useEffect
顺便说一句,我想您希望将数据保存在 React.useEffect(() => {
console.log(post);
}, [post]);
中,因此您可能会保存从HTTP响应正文中检索到的JSON,您可以使用{{1} }。
编辑:如Siradji Awoual的评论所述,我写的关于response
和response.json()
的内容对Axios无效(但对于{{1 }} API)。
答案 1 :(得分:0)
设置状态是异步的。这意味着您不知道该动作何时完成执行。
如果我是你,我将使用诸如useEffect之类的方法来检查状态是否已设置。
React.useEffect(() => console.log(post), [post])
答案 2 :(得分:0)
使用axios.get
是低级的,它要求您添加很多额外的内容才能正常工作。相反,请尝试编写自定义钩子以抽象该逻辑-
const identity = x => x
const useAsync = (runAsync = identity, deps = []) => {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
Promise.resolve(runAsync(...deps))
.then(setResult, setError)
.finally(_ => setLoading(false))
}, deps)
return { loading, error, result }
}
使用useAsync
看起来像这样-
const MyApp = () => {
const { loading, error, result } =
useAsync(_ => axios.get("./foo.json").then(res => res.json()))
if (loading)
return <p>loading...</p>
if (error)
return <p>error: {error.message}</p>
return <pre>result: {result}</pre>
}
但是您可能会有许多获取JSON的组件,对吗?我们可以制作一个更高级别的自定义钩子useJSON
,它是useAsync
-
const fetchJson = (url = "") =>
axios.get(url).then(r => r.json()) // <-- stop repeating yourself
const useJson = (url = "") =>
useAsync(fetchJson, [url]) // <-- useAsync
const MyApp = () => {
const { loading, error, result } =
useJson("./foo.json") // <-- dead simple
if (loading)
return <p>loading...</p>
if (error)
return <p>error: {error.message}</p>
return <pre>result: {result}</pre>
}
请参见此功能代码段中的自定义钩子-
const { useState, useEffect } =
React
// fake fetch slows response down so we can see loading
const _fetch = (url = "") =>
fetch(url).then(x =>
new Promise(r => setTimeout(r, 2000, x)))
const identity = x => x
const useAsync = (runAsync = identity, deps = []) => {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
Promise.resolve(runAsync(...deps))
.then(setResult, setError)
.finally(_ => setLoading(false))
}, deps)
return { loading, error, result }
}
const fetchJson = (url = "") =>
_fetch(url).then(r => r.json())
const useJson = (url = "") =>
useAsync(fetchJson, [url])
const MyComponent = ({ url = "" }) => {
const { loading, error, result } =
useJson(url)
if (loading)
return <pre>loading...</pre>
if (error)
return <pre style={{color: "tomato"}}>error: {error.message}</pre>
return <pre>result: {JSON.stringify(result, null, 2)}</pre>
}
const MyApp = () =>
<main>
ex 1 (success):
<MyComponent url="https://httpbin.org/get?foo=bar" />
ex 2 (error):
<MyComponent url="https://httpbin.org/status/500" />
</main>
ReactDOM.render(<MyApp />, document.body)
pre {
background: ghostwhite;
padding: 1rem;
white-space: pre-wrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>