reactjs - React Hooks:useEffect、useReducer、createContext 和 localStorage;TypeError:无法读取未定义的属性
问题描述
我在我的地图应用程序中使用本地存储来进行一些持久存储;还使用 React.createContext 和 useReducer 在组件之间共享和更新状态。
本地存储中的状态,以及控制台中的应用程序中的状态正在更新和呈现,即哈希生成的 id,来自 Cloudinary 的图像路径。
但是当我点击地图添加标记时,我得到:
TypeError:无法读取未定义的属性“标记”
这很奇怪,因为我在控制台和本地存储中看到了什么。
我的想法是我的接线错误。
我的 UserContext 组件:
var initialState = {
avatar: '/static/uploads/profile-avatars/placeholder.jpg',
id: null,
isRoutingVisible: false,
removeRoutingMachine: false,
isLengthOfMarkersLessThanTwo: true,
markers: [],
currentMap: {}
};
var UserContext = React.createContext();
function UserProvider({ children }) {
function userReducer(state, { type, payload }) {
switch (type) {
case 'setUserId': {
return { ...state, ...{ id: payload.id } };
}
case 'setAvatar': {
return {
...state,
...{ avatar: payload.avatar }
};
}
case 'setIsRoutingVisible': {
return {
...state,
...{ isRoutingVisible: payload.isRoutingVisible }
};
}
case 'isLengthOfMarkersLessThanTwoFalse': {
return {
...state,
...{
isLengthOfMarkersLessThanTwo: payload.isLengthOfMarkersLessThanTwo
}
};
}
case 'addMarker': {
user.isLengthOfMarkersLessThanTwo
? {
...state,
markers: user.markers.concat(payload.marker)
}
: null;
break;
}
default: {
throw new Error(`Unhandled action type: ${type}`);
}
}
}
const [user, setUser] = useState(() => getLocalStorage('user', initialState));
var [state, dispatch] = useReducer(userReducer, user);
const [isAvatarUploading, setIsAvatarUploading] = useState(true);
useEffect(() => {
setLocalStorage('user', state);
}, [state]);
useEffect(() => {
console.log('state', state);
if (state.markers.length === 2) {
dispatch({
type: 'isLengthOfMarkersLessThanTwoFalse',
payload: { isLengthOfMarkersLessThanTwo: false }
});
}
}, [JSON.stringify(state.markers)]);
useEffect(() => {
console.log('state', state);
if (state.id) {
getUserAvatar()
.then(userAvatar => {
console.log('userAvatar ', userAvatar);
setIsAvatarUploading(false);
dispatch({
type: 'setAvatar',
payload: { avatar: userAvatar }
});
})
.catch(err => console.log('error thrown from getUserAvatar', err));
} else {
console.log('No user yet!');
}
}, [state.id]);
return (
<UserContext.Provider
value={{
userId: state.id,
userAvatar: state.avatar,
dispatch: dispatch,
isAvatarUploading: state.isAvatarUploading,
userImages: state.images,
userMarkers: state.markers,
userMap: state.currentMap,
removeRoutingMachine: state.removeRoutingMachine,
isRoutingVisibile: state.isRoutingVisible
}}
>
{children}
</UserContext.Provider>
);
}
export default UserContext;
export { UserProvider };
我想我需要一个自定义钩子,用来传递旧状态并用它来观察变化和更新它。
var newUserState = initialState => {
const [state, setState] = useState(initialState);
var setter = useCallback(() => setState(state => !state), [setState]);
return [state, setter];
};
var [newUserState, setter] = newUserState(state)
任何帮助将不胜感激!
解决方案
在您的addMarker
情况下,您可能想要访问局部state
变量而不是全局变量user
。
另外,根据我对这个其他问题的答案的理解,您宁愿在组件之外定义减速器,因为当您重新定义减速器功能时,React 会触发一些不需要的更新。
这些是否能解决你的问题,我不能说......
推荐阅读
- java - 广播接收器无法从新意图中获取新值并显示以前的值
- dart - 无法使用自定义运算符重载扩展 Num 以实现可交换规则
- laravel - 简单的一对多关系 laravel
- android - Android 应用程序在设备上运行,但在 Playstore 中不兼容
- windows - 从多个目录复制文件并在其他单独的文件夹中创建相同的结构 [Windows]
- c# - 如何缩短 LINQ 查询以从子表中计算父表的总和
- python - QQ地块分布检查
- node.js - mongoose findOne,我如何从对象数组中找到一个元素?
- javascript - 如何用 json 数据填充选择?
- npm - Webpack externals - 不是所有的依赖都已经是外部的了吗?