无法在反应中的获取响应中访问深层嵌套对象
cannot access deep nested objects in fetch response in react
所以我在 Stack 和网络上偶然发现了很多示例,其中从未定义的异步提取调用访问深层嵌套对象。很多答案都解决了其他文章导致访问对象和数组的方式。其他人声称这是异步操作的原因。不过我实在想不通。
这是数据:
base: "stations"
clouds: {all: 1}
cod: 200
coord: {lon: -81.38, lat: 28.54}
dt: 1607561322
id: 4167147
main: {temp: 51.28, feels_like: 45.97, temp_min: 48.99, temp_max: 53.6, pressure: 1021, …}
name: "Orlando"
sys: {type: 1, id: 5234, country: "US", sunrise: 1607515628, sunset: 1607552963}
timezone: -18000
visibility: 10000
weather: [{…}]
wind: {speed: 4.52, deg: 271}
这是代码,注意 useEffect 回调中的 setWeatherData
function WeatherDisplay(props){
const [weatherData, setWeatherData] = useState({})
useEffect(() => {
fetch(`http://api.openweathermap.org/data/2.5/weather?q=Orlando&units=imperial&appid=3abd9c2df6a249e8abcf4f812de0a627`)
.then(res => res.json())
.then(data => {
setWeatherData({
data,
name: data.name,
main: data.main,
...data.main
})
})
.catch(err => console.log(err))
}, [])
return(
<>
<Media style={{backgroundColor: "gray", borderRadius: "5px", height: "5.5rem"}}>
<IconContext.Provider value={{size: "5rem", style:{fontWeight: "200"}, className:"align-self-center"}}>
<TiWeatherPartlySunny />
</IconContext.Provider>
{console.log(weatherData)}
{console.log(weatherData.name)}
{console.log(weatherData.main)}
{console.log(weatherData.temp)}
</Media>
</>
)
}
这就是开始的方式
首先,我只是将天气数据设置为数据,因为我可以渲染 weatherData.name (Orlando) 但由于某种原因 weatherData.main.temp 返回错误,因为 weatherData.main 结果未定义。我四处询问,他们说这是因为 promises 并且它是异步的,所以我必须使用条件等等,但这仍然不能解释它是如何访问 weatherData.name 的。 weatherData.clouds 和 .sys
也一样
我继续传播我想要的对象的值,但我能想到我的解决方法不会有用的简单情况。
我想知道这是否是 React 保存深层嵌套对象值的方式,但我真的不知道。
如果你设置如下
setWeatherData({
data
})
您的天气数据将是
{
data: {
main: {...},
name: '...'
sys: {...}
}
}
要访问 main,您应该使用
weatherData.data.main
是的,这是因为异步行为。 weatherData
对象将始终存在(最初作为 {},然后在请求完成后与获取的数据一起存在)。
在初始渲染中,weatherData.name
将等于 {}.name
,这将 return 未定义,但不会导致错误。
然而,当您 运行 weatherData.main.temp
时,它将等于 {}.main.temp
,这意味着您实际上是在调用 undefined.temp
,这将引发错误。只有当 main
属性未定义时才会抛出此错误,这意味着一旦实际获取数据它就应该正常工作。
您可以通过几种不同的方式解决这个问题,我推荐以下两种方式之一:
如果获取尚未完成,则呈现“正在加载数据...”等的条件渲染。
条件访问器。尝试访问 weatherData.main?.temp
而不是 weatherData.main.temp
。不确定它是否可以在 JSX 内部工作,但假设您使用的是最新版本的 babel,它将正确地转换条件分支,它应该可以在外部工作。
您还可以创建一个初始 weatherData
对象,其中定义了预期的接口,但所有值都设置为 undefined
。
换句话说,
const initialWeatherData = {
name: undefined,
main: {
temp: undefined,
}
}
// etc, leaving out most of the object as I'm sure you get what I'm trying to do
// just make sure you define the entire interface
const [weatherData, setWeatherData] = useState(initalWeatherData);
你用这个代码和 API 图片来理解这个想法。希望对您有所帮助
import React from 'react'
class GetData extends React.Component {
state = {
data: []
};
async componentDidMount() {
try {
const url = "http://localhost:8000/blogList";
const response = await fetch(url);
const data = await response.json();
console.log(data);
this.setState({ data: data.result });
} catch (err) {
console.log(err);
}
}
render() {
const { data } = this.state
return (
<div>{
<ul>
{data.map((item, i) => {
return <li key={item.id}>{item.title}</li>
})}
</ul>
}
</div>
);
}
}
export default GetData
所以我在 Stack 和网络上偶然发现了很多示例,其中从未定义的异步提取调用访问深层嵌套对象。很多答案都解决了其他文章导致访问对象和数组的方式。其他人声称这是异步操作的原因。不过我实在想不通。
这是数据:
base: "stations"
clouds: {all: 1}
cod: 200
coord: {lon: -81.38, lat: 28.54}
dt: 1607561322
id: 4167147
main: {temp: 51.28, feels_like: 45.97, temp_min: 48.99, temp_max: 53.6, pressure: 1021, …}
name: "Orlando"
sys: {type: 1, id: 5234, country: "US", sunrise: 1607515628, sunset: 1607552963}
timezone: -18000
visibility: 10000
weather: [{…}]
wind: {speed: 4.52, deg: 271}
这是代码,注意 useEffect 回调中的 setWeatherData
function WeatherDisplay(props){
const [weatherData, setWeatherData] = useState({})
useEffect(() => {
fetch(`http://api.openweathermap.org/data/2.5/weather?q=Orlando&units=imperial&appid=3abd9c2df6a249e8abcf4f812de0a627`)
.then(res => res.json())
.then(data => {
setWeatherData({
data,
name: data.name,
main: data.main,
...data.main
})
})
.catch(err => console.log(err))
}, [])
return(
<>
<Media style={{backgroundColor: "gray", borderRadius: "5px", height: "5.5rem"}}>
<IconContext.Provider value={{size: "5rem", style:{fontWeight: "200"}, className:"align-self-center"}}>
<TiWeatherPartlySunny />
</IconContext.Provider>
{console.log(weatherData)}
{console.log(weatherData.name)}
{console.log(weatherData.main)}
{console.log(weatherData.temp)}
</Media>
</>
)
}
这就是开始的方式 首先,我只是将天气数据设置为数据,因为我可以渲染 weatherData.name (Orlando) 但由于某种原因 weatherData.main.temp 返回错误,因为 weatherData.main 结果未定义。我四处询问,他们说这是因为 promises 并且它是异步的,所以我必须使用条件等等,但这仍然不能解释它是如何访问 weatherData.name 的。 weatherData.clouds 和 .sys
也一样我继续传播我想要的对象的值,但我能想到我的解决方法不会有用的简单情况。
我想知道这是否是 React 保存深层嵌套对象值的方式,但我真的不知道。
如果你设置如下
setWeatherData({
data
})
您的天气数据将是
{
data: {
main: {...},
name: '...'
sys: {...}
}
}
要访问 main,您应该使用
weatherData.data.main
是的,这是因为异步行为。 weatherData
对象将始终存在(最初作为 {},然后在请求完成后与获取的数据一起存在)。
在初始渲染中,weatherData.name
将等于 {}.name
,这将 return 未定义,但不会导致错误。
然而,当您 运行 weatherData.main.temp
时,它将等于 {}.main.temp
,这意味着您实际上是在调用 undefined.temp
,这将引发错误。只有当 main
属性未定义时才会抛出此错误,这意味着一旦实际获取数据它就应该正常工作。
您可以通过几种不同的方式解决这个问题,我推荐以下两种方式之一:
如果获取尚未完成,则呈现“正在加载数据...”等的条件渲染。
条件访问器。尝试访问
weatherData.main?.temp
而不是weatherData.main.temp
。不确定它是否可以在 JSX 内部工作,但假设您使用的是最新版本的 babel,它将正确地转换条件分支,它应该可以在外部工作。您还可以创建一个初始
weatherData
对象,其中定义了预期的接口,但所有值都设置为undefined
。
换句话说,
const initialWeatherData = {
name: undefined,
main: {
temp: undefined,
}
}
// etc, leaving out most of the object as I'm sure you get what I'm trying to do
// just make sure you define the entire interface
const [weatherData, setWeatherData] = useState(initalWeatherData);
你用这个代码和 API 图片来理解这个想法。希望对您有所帮助
import React from 'react'
class GetData extends React.Component {
state = {
data: []
};
async componentDidMount() {
try {
const url = "http://localhost:8000/blogList";
const response = await fetch(url);
const data = await response.json();
console.log(data);
this.setState({ data: data.result });
} catch (err) {
console.log(err);
}
}
render() {
const { data } = this.state
return (
<div>{
<ul>
{data.map((item, i) => {
return <li key={item.id}>{item.title}</li>
})}
</ul>
}
</div>
);
}
}
export default GetData