首页 > 解决方案 > 关于从 Slice 到 index.js 的响应数据的问题 - React redux 工具包

问题描述

我想从 API 获取数据并尝试在 index.js 中使用

错误:

TypeError:无法读取未定义的属性(读取“图标”)

当我 console.log 它打印

index.js 的空数组 > weatherSlice.js 的响应数据 > 最后 index.js 的响应数据作为一个数组

我遇到了未定义的错误并尝试了这个并且有点工作。

{getCity.length !== 0 && (
<Typography variant="h6"  component="div">
 <div>Wind : {getCity.current.gust_kph} kph</div>
 <div>Pressure: {getCity.current.pressure_in} in</div>
</Typography>
                )}

但是这次它在这个块上给出了同样的错误

{getCity.length !== 0 && (
  <Grid item xs={3} sx={{mb:3}}>
    <div  className="label">{getDate()}</div>
    <div className="label"> <img src={`${getCity.forecast.forecastday[1].condition.icon}`} alt="" /></div> // Gives undefined (reading"icon")
    <div className="label" >22 C</div> 
  </Grid>)}

索引.js

const dispatch = useDispatch();
const [selectedCity, setSelectedCity] = useState('Ankara');
const getCity  = useSelector((state) => state.weather.item);
const [datee , setDate ] = useState('');

useEffect(() => {
    dispatch(fetchDefault(selectedCity))   
    setDate(getDate())
}, [dispatch])

天气切片

export const fetchDefault = createAsyncThunk('weather/getWeather', async (selectedCity) => {
const res = await axios(`http://api.weatherapi.com/v1/forecast.json?key=ebb6c0feefc646f6aa6124922211211&q=${selectedCity}&days=10&aqi=no&alerts=no
`)
return res.data});

export const weatherSlice = createSlice({   
name: "weather",
initialState : {
    item : [],
},
reducers:{},
extraReducers:{
    [fetchDefault.fulfilled]: (state , action) => {
       
        state.item = action.payload;
        
        console.log(state.item)
         
    },
    [fetchDefault.pending]: (state , action) => {
       
        console.log("sadsad")
    }
}

标签: javascriptreactjsreduxreact-redux

解决方案


填充状态后,state.weather.item它现在是一个对象,而不是数组。初始条件getCity.length !== 0有效/通过,因为getCity.lengthisundefined并且undefined !== 0评估为 true。在您开始访问该状态后会出现此问题。

获取的城市数据是一个具有locationcurrentforecast属性的对象。

// 20211114135700
// https://api.weatherapi.com/v1/forecast.json?key=ebb6c0feefc646f6aa6124922211211&q=seattle&days=10&aqi=no&alerts=no

{
  "location": {
    "name": "Seattle",
    "region": "Washington",
    "country": "United States of America",
    "lat": 47.61,
    "lon": -122.33,
    "tz_id": "America/Los_Angeles",
    "localtime_epoch": 1636927019,
    "localtime": "2021-11-14 13:56"
  },
  "current": {
    "last_updated_epoch": 1636926300,
    "last_updated": "2021-11-14 13:45",
    "temp_c": 16.1,
    "temp_f": 61.0,
    "is_day": 1,
    "condition": {
      "text": "Light rain",
      "icon": "//cdn.weatherapi.com/weather/64x64/day/296.png",
      "code": 1183
    },
    "wind_mph": 13.6,
    "wind_kph": 22.0,
    "wind_degree": 190,
    "wind_dir": "S",
    "pressure_mb": 1014.0,
    "pressure_in": 29.94,
    "precip_mm": 1.0,
    "precip_in": 0.04,
    "humidity": 90,
    "cloud": 100,
    "feelslike_c": 16.1,
    "feelslike_f": 61.0,
    "vis_km": 3.2,
    "vis_miles": 1.0,
    "uv": 4.0,
    "gust_mph": 18.8,
    "gust_kph": 30.2
  },
  "forecast": {
    "forecastday": [
      {
        "date": "2021-11-14",
        "date_epoch": 1636848000,
        "day": {
          "maxtemp_c": 16.2,
          "maxtemp_f": 61.2,
          "mintemp_c": 11.5,
          "mintemp_f": 52.7,
          "avgtemp_c": 14.9,
          "avgtemp_f": 58.8,
          "maxwind_mph": 16.1,
          "maxwind_kph": 25.9,
          "totalprecip_mm": 21.1,
          "totalprecip_in": 0.83,
          "avgvis_km": 9.3,
          "avgvis_miles": 5.0,
          "avghumidity": 93.0,
          "daily_will_it_rain": 1,
          "daily_chance_of_rain": 99,
          "daily_will_it_snow": 0,
          "daily_chance_of_snow": 0,
          "condition": {
            "text": "Heavy rain",
            "icon": "//cdn.weatherapi.com/weather/64x64/day/308.png",
            "code": 1195
          },
          "uv": 1.0
        },
        "astro": {
          ...
        },
        "hour": [
          ...
        ]
      },
      ...
    ]
  }
}

您正在尝试渲染forecast,但这是代码真正横向的地方。您假设至少有2 个元素(即 getCity.forecast.forecastday.length>= 2), and then if there is, assume theres a条件property. When there isn't andgetCity.forecast.forecastday[1].condition` 未定义,这是您看到的错误。

据我所知,该condition属性嵌套在一个day字段中。由于尚不清楚响应数据中保证存在哪些属性,因此最好的选择是:

  1. 首先确保您访问的是正确的路径
  2. 使用 null-checks/guard-clauses 或 Optional Chaining operator 来防止意外的 null/undefined 访问

更新后的对象属性路径如下:

getCity.forecast.forecastday.[1].day.condition.icon

如果其中任何一个可能未定义或未在数据中返回,则使用可选链接运算符的更正访问如下:

getCity.forecast?.forecastday?.[1]?.day?.condition?.icon

这是等效的 null-check/guard-clause 版本:

getCity.forecast 
  && getCity.forecast.forecastday
  && getCity.forecast.forecastday[1]
  && getCity.forecast.forecastday[1].day
  && getCity.forecast.forecastday[1].day.condition
  && getCity.forecast.forecastday[1].day.condition.icon

current对天气数据使用相同类型的检查:

{getCity.current && (
  <Typography variant="h6" component="div">
    <div>Wind : {getCity.current.gust_kph} kph</div>
    <div>Pressure: {getCity.current.pressure_in} in</div>
  </Typography>
)}

最后,更新天气切片的初始状态以匹配数据不变量,它应该是一个对象。

initialState : {
  item : {},
},

推荐阅读