问题描述
我正在尝试从来自 API 的以下数据对象呈现数据。
{
"code": 0,"c": "verified","d": "verified","leaseInfo": {
"infoId": 6
},"cpfPrice": "500.00","carCurrentLocation": {
"id": 1,"carId": "df47a56a395a49b1a5d06a58cc42ffc4"
},"n": "verified","p": "false","ownerCarInfo": {
"brand": "Ferrari","model": "0"
},"serviceFeeRate": 0.10,"depositPrice": "100.00","pics": [
{
"picid": 49,"carId": "df47a56a395a49b1a5d06a58cc42ffc4"
},],"items": {
"itemid": 5,"carId": "df47a56a395a49b1a5d06a58cc42ffc4"
}
}
我正在使用 react-redux
分派一个动作,在那里我将获得名为“carDetails
”的状态下的数据。
但是,当我尝试访问数据时,如果我的组件被刷新,carDetails
变为 undefined
,因此给出“Cannot read property ownerCarInfo of undefined.
”
我正在 React 组件中像这样获取和解构 carDetails
的数据:
import React,{useEffect} from 'react';
import { usedispatch,useSelector } from 'react-redux';
const CarInfo = ({ match }) => {
const dispatch = usedispatch();
const details = useSelector((state) => state.carDetails);
const { loading,carDetails } = details;
const {pics,carCurrentLocation,items,ownerCarInfo} = carDetails;
useEffect(() => {
dispatch(getCarDetails(match.params.id));
},[dispatch,match]);
return (
<div>
{loading ? (
<Loader></Loader>
) : (
<>
<p>{d.depositPrice}</p>
<p>{ownerCarInfo.brand}</p>
</>
)}
</div>
); )
}
只要组件或 React
应用程序未刷新,它就会检索数据并正确显示。刷新页面后,carDetails
立即变为空数组。
这是 getCarDetails()
操作:
export const getCarDetails = (id) => async (dispatch,getState) => {
try {
dispatch({
type: CAR_DETAILS_REQUEST,});
const { userLogin } = getState();
const { userInfo } = userLogin;
const config = {
headers: {
Authorization: userInfo.token,'Content-Type': 'application/json',},};
const { data } = await axios.get(
`${BASE_API}/car/info/getDetails/${id}/${userInfo.bscId}`,config
);
dispatch({
type: CAR_DETAILS_SUCCESS,payload: data,});
} catch (error) {
dispatch({
type: CAR_DETAILS_FAIL,payload:
error.response && error.response.data.msg
? error.response.data.msg
: error.msg,});
}
};
这是我的减速器:
export const carsDetailsReducer = (state = { carDetails: [] },action) => {
switch (action.type) {
case CAR_DETAILS_REQUEST:
return { loading: true };
case CAR_DETAILS_SUCCESS:
return { loading: false,carDetails: action.payload };
case CAR_DETAILS_FAIL:
return { loading: false,error: action.payload };
default:
return state;
}
};
这就是我在 redux 存储中声明 carDetails
的方式。
const reducer = combineReducers({
carDetails: carsDetailsReducer,});
carDetails
未定义且 useEffect
未在页面刷新时运行的原因是什么?
解决方法
问题出在CAR_DETAILS_REQUEST
。您只返回 { loading: true };
,因此 carDetails
将丢失并变为 undefined
。
只需像这样更新您的减速器:
case CAR_DETAILS_REQUEST:
return { ...state,loading: true };
,
如果 carDetails
初始状态是一个数组,那么您为什么要在 UI 中从中解构对象属性?再问一次...
如果重新加载页面后状态恢复到初始状态,则空数组仍然是已定义的对象。您需要找出导致 state.carDetails.carDetails
未定义的原因。如果您检查您的减速器,请注意您的 CAR_DETAILS_REQUEST
情况会清除 carDetails
状态并变为 undefined
。老实说,当您的代码在没有重新加载页面的情况下正常运行时,您没有看到此问题,我感到很惊讶。
你需要保持那个状态。为了更好地衡量,除非您有充分的理由省略部分状态,否则在计算下一个状态对象时,您应该始终浅复制现有状态。
export const carsDetailsReducer = (state = { carDetails: [] },action) => {
switch (action.type) {
case CAR_DETAILS_REQUEST:
return {
...state,// <-- shallow copy existing state
loading: true,};
case CAR_DETAILS_SUCCESS:
return {
...state,// <-- shallow copy existing state
loading: false,carDetails: action.payload
};
case CAR_DETAILS_FAIL:
return {
...state,error: action.payload,};
default:
return state;
}
};
,
如果您使用 axios
,您的操作应该与 async
函数和 await
类似strong> 在您调用 API 时。
如果您在 api
链接中传递 API 汽车 ID,则在参数中传递 id
:
import axios from "axios";
export const loadData = (id) => async (dispatch) => {
dispatch({
type: "CAR_DETAILS_REQUEST",});
const detailData = await axios.get("http:\\****/id");
dispatch({
type: "CAR_DETAILS_SUCCESS",payload: {
success: detailData.data,},});
};
减速器:
const initailState = { carDetails: [],loading: true };
export const carsDetailsReducer = (state = initailState,action) => {
switch (action.type) {
case CAR_DETAILS_REQUEST:
return { ...state,loading: true
};
case CAR_DETAILS_SUCCESS:
return {...state,loading: false,carDetails: action.payload
};
case CAR_DETAILS_FAIL:
return { ...state,error: action.payload };
default:
return ...state;
}
};
您的 useEffect 应该只在获取数据时起作用:
import React,{useEffect} from 'react';
import { useDispatch,useSelector } from 'react-redux';
const CarInfo = ({ match }) => {
const dispatch = useDispatch();
const details = useSelector((state) => state.carDetails);
const { loading,carDetails } = details;
const {pics,carCurrentLocation,items,ownerCarInfo} = carDetails;
useEffect(() => {
dispatch(getCarDetails(id));
},[dispatch]);
return (
<div>
{loading ? (
<Loader></Loader>
) : (
<>
<p>{d.depositPrice}</p>
<p>{ownerCarInfo.brand}</p>
</>
)}
</div>
您也可以在没有 useEffect
的情况下使用它,方法是创建一个像这样的 onclick()
函数:
const loadDetailHandler = () => {
dispatch(getCarDetails(id));
};
return (
<div onClick={loadDetailHandler} >
</div>
,
对我来说,我认为你应该将状态保存在
`case CAR_DETAILS_REQUEST:
return {
...state,};
`
为了能够在 o 之前使用它,当您想使用减速器时,您应该每种情况
让旧状态减速器返回相同的初始状态,您也使用它正在加载并且在初始状态中找不到
所以尽量做状态的形状
state={
isloading:false,carDetails: []
}
也尝试每次通过 {...state,is loading:true}