axios
でReact
を使用してUseEffect
経由でAPI呼び出しを行っています。
_data
を使用して、useState
という変数に応答を設定します
_const [data, setData] = useState({});
setData(response);
_
応答はNASA APIからのものであり、この呼び出しに対して返されるオブジェクトは1つだけです(以下に貼り付けます)。
応答に「data」という名前を付け、それに「data」キーもあるので、URLをログに記録したい場合は、console.log(data.data.url)
と入力すると、_app.js
_でスムーズに機能します。主な機能。私の_card.js
_コンポーネントでは、console.log(data)
とconsole.log(data.data)
を正常にログに記録でき、期待どおりの結果が得られますが、console.log(data.data.url)
または_(data.data.title)
_何らかの理由でundefined
になるため、JSXのreturn関数で大きなエラーが発生し、サイトが読み込まれません。
_ TypeError: Cannot read property 'data' of undefined error.
_
それはオブジェクトのより高いレベルでうまく機能するので、私は自分の名前付けに何か問題があるとは思いません。 console.log(data.data)
が機能し、目の前に次のレベルのプロパティが表示されます。
私は文字通りconsole.logingしています:
_{console.log('FROM INSIDE THE RETURN')}
{console.log(props.data)} // works, displays object {}
{console.log(props.data.data)} //works, displays object one level lower
{console.log(props.data.data.url)} // type error. You name the property.
_
言うまでもなく、これは機能しません。これが割り当てへの私の最初のアプローチでした。
_<img src={props.data.data.url}/>
_
それは、次のように上流のオブジェクトのトップレイヤーを削って、チームリーダーの助けを借りてプログラムを機能させることを意味します。
_SetData(response.data)
// as opposed to
SetData(response)
// and then using
<img src={props.data.url}/>
_
したがって、小道具の最下部に到達する必要はありませんでしたが、明確にするために、特にn-1層まで正常に機能した場合に、コンパイラーがコンパイラーに与える理由と違いを知りたいと思います(nは数値)オブジェクトのレイヤーの。
'data'が重複せず、動作が同じになるように、データ変数の1つの名前を変更しました。
あなたの助けと洞察をありがとう!あなたが共有できる洞察と私の質問に対するフィードバックに本当に感謝しています。
これが私が作業しているオブジェクトです。
_ {
data: {
copyright: "Bryan Goff",
date: "2020-03-18",
explanation: "What's happening behind...[truncated]...Florida, USA.",
hdurl: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_3072.jpg",
media_type: "image",
service_version: "v1",
title: "Anticrepuscular Rays over Florida",
url: "https://apod.nasa.gov/apod/image/2003/AntiCrepRays_Goff_960.jpg"
},
status: 200,
statusText: "OK",
headers: {
contenttype: "application/json"
},
config: {
url: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY",
method: "get",
headers: {
Accept: "application/json, text/plain, */*"
},
transformRequest: [
null
],
transformResponse: [
null
],
timeout: 0,
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
maxContentLength: -1
},
request: {}
}
_
これは確かに興味深い課題です。
ステップバイステップの分析をして、私たちが同意するかどうか見てみましょう:
// this initializes `data = {}` when the app first launches
const [data, setData] = useState({});
// Chances are, you are using this within the "useEffect"
// If so at that point, the above `data = response`
setData(response)
ほとんどの場合、axios
内でuseEffect
NASA API呼び出しを行っています。
それでは、API呼び出しに絞り込みましょう。
多くの場合、API呼び出しは非同期です(非ブロッキング)。
つまり、このデータフェッチプロセスは、クライアント側が他の「アクティビティ」を実行することを妨げません。それが邪魔にならないように、共有コードに戻ってみましょう:
説明1:データのフェッチ中に発生する可能性があります
// works, because initially "data = {}"
{console.log(props.data)}
// works, displays object one level lower
{console.log(props.data.data)}
// Explaining this...
// APIs are often backend apps that query a database for actual data.
// This returned data is stored in "literals" (often arrays/lists/objects).
// type error. You name the property.
{console.log(props.data.data.url)}
// Based on the above explanation,
// despite the second `data` being an Object literal,
// "url" isn't yet defined since the API is still "querying" the database
説明2:名前空間の競合の可能性があります
// If all is fine based on "explanation 1",
// then this could be a "namespace" conflict during compilation.
// At compilation, JS finds two variables named "data"
// 1. The initial data value,
data = {}
// 2. The returned data key,
{
data: {...},
}
// If we had a returned response as follows:
results = {
data: {...},
}
// we probably would have something like this working
{console.log(response.data.result.data.url)}
// And this might explains why these work...
{console.log(response.data.url)}
<img src={props.data.url}/>
ここでは、頑固なJavaScriptを扱っています。
そして、そのため、現在増加している多くの大きなReactjs
プロジェクトがTypeScript
に関与しているのはおそらくそのためです。
私の推測では、api呼び出しに時間がかかり、api呼び出しが戻る前に値を設定しようとしています。追加のisLoading状態を使用して、APIがまだ実行されているかどうかを確認してください
import React from 'react';
const Component = () => {
const [isLoading,setIsLoading] = useState(true)
const [data, setData] = useState({});
useEffect(()=>{
setTimeout(()=>fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(json => {
setData(json)
setIsLoading(false)
}),1000)
},[0])
return(
isLoading ? 'Loading...' :
<div>
<h1>Hello {data.name}!</h1>
<p>Your username is {data.username}</p>
</div>
)
}
export default Component