我正在使用这篇文章来帮助使用useReducer
钩子。
我创建了这个上下文组件,因为我正在使用react-leaflet路由机器为路线创建标记,并且我想将纬度和经度保存在本地存储中;我最初可以保存它们,但我无法更新它们!
基本上在我的UserContext
组件中,我创建了这个reducer函数:
function userReducer(state, { type, payload }) {
switch (type) {
case 'isLengthOfMarkersLessThanTwoFalse': {
return {
...state,
isLengthOfMarkersLessThanTwo: payload.isLengthOfMarkersLessThanTwo
};
}
case 'updateMarkers': {
console.log('type, payload ', type, payload);
return {
...state,
...state.markers.map(element => {
console.log('element.alt === payload.alt ', element.alt === payload.alt);
return element.alt === payload.alt ? { ...element, ...payload } : element;
})
};
}
default: {
throw new Error(`Unhandled action type: ${type}`);
}
}
}
所以你可以看到有一个console.log
in case 子句,
case 'updateMarkers': {
console.log('type, payload ', type, payload);
return {
...state,
type, payload updateMarkers LatLng {lat: 40.74154270838886, lng: -73.76230053137989, alt: "current location"} alt: "current location"lat: 40.74154270838886lng: -73.76230053137989
所以它实际上是在减速器中传递,但状态没有被更新!
This is the complete component :
import React, { useState, useEffect, useReducer } from 'react';
import { getUserAvatar } from '../../utils/index';
import { parse, stringify } from 'flatted';
var initialState = {
avatar: '/static/uploads/profile-avatars/placeholder.jpg',
isRoutingVisible: false,
removeRoutingMachine: false,
isLengthOfMarkersLessThanTwo: true,
markers: [],
currentMap: {}
};
var UserContext = React.createContext();
function setLocalStorage(key, value) {
function isJson(item) {
item = typeof item !== 'string' ? JSON.stringify(item) : item;
try {
item = JSON.parse(item);
} catch (e) {
return false;
}
if (typeof item === 'object' && item !== null) {
return true;
}
return false;
}
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (errors) {
// catch possible errors:
console.log(errors);
}
}
function getLocalStorage(key, initialValue) {
try {
const value = window.localStorage.getItem(key);
return value ? JSON.parse(value) : initialValue;
} catch (e) {
return initialValue;
}
}
function UserProvider({ children }) {
const [user, setUser] = useState(() => getLocalStorage('user', initialState));
const [isAvatarUploading, setIsAvatarUploading] = useState(true);
function userReducer(state, { type, payload }) {
switch (type) {
case 'isLengthOfMarkersLessThanTwoFalse': {
return {
...state,
isLengthOfMarkersLessThanTwo: payload.isLengthOfMarkersLessThanTwo
};
}
case 'updateMarkers': {
console.log('type, payload ', type, payload);
return {
...state,
...state.markers.map(element => {
console.log('element.alt === payload.alt ', element.alt === payload.alt);
return element.alt === payload.alt ? { ...element, ...payload } : element;
})
};
}
default: {
throw new Error(`Unhandled action type: ${type}`);
}
}
}
const [state, dispatch] = useReducer(userReducer, initialState);
// console.log('user ', user);
useEffect(() => {
setLocalStorage('user', user);
}, [user]);
useEffect(() => {
console.log('user.isRoutingVisibile ', user.isRoutingVisibile);
}, [user.isRoutingVisibile]);
useEffect(() => {
console.log('state', state);
if (user.markers.length === 2) {
dispatch({
type: 'isLengthOfMarkersLessThanTwoFalse',
payload: { isLengthOfMarkersLessThanTwo: false }
});
}
}, [JSON.stringify(user.markers)]);
useEffect(() => {
if (user.id) {
getUserAvatar()
.then(userAvatar => {
setIsAvatarUploading(false);
setUser(user => ({ ...user, avatar: userAvatar }));
})
.catch(err => console.log('error thrown from getUserAvatar', err));
} else {
console.log('No user yet!');
}
}, [user.id]);
return (
<UserContext.Provider
value={{
userId: user.id,
setUserId: id => setUser({ ...user, id }),
userAvatar: user.avatar,
setUserAvatar: avatar => setUser({ ...user, avatar }),
isAvatarUploading: isAvatarUploading,
userImages: user.images,
setUserImages: images => setUser({ ...user, images }),
userMarkers: user.markers,
setUserMarkers: marker => {
state.isLengthOfMarkersLessThanTwo
? setUser(user => ({
...user,
markers: [...user.markers, marker]
}))
: () => null;
},
setUpdateUserMarker: dispatch,
deleteUserMarkers: () => {
setUser({
...user,
markers: [
...user.markers.filter(function(e, i, a) {
return e !== a[a.length - 1];
})
]
});
},
setUserMarkersToNull: () =>
setUser({
...user,
markers: null
}),
userMap: user.currentMap,
setUserCurrentMap: map =>
setUser({ ...user, currentMap: { ...user.currentMap, map } }),
removeRoutingMachine: user.removeRoutingMachine,
resetUserMarkers: () => {
console.log('fired setIsRoutingVisibileToTrue');
setUser({
...user,
removeRoutingMachine: true,
isRoutingVisible: false,
markers: []
});
},
isRoutingVisibile: user.isRoutingVisible,
setIsRoutingVisibileToTrue: () => {
console.log('fired setIsRoutingVisibileToTrue');
setUser({
...user,
isRoutingVisible: true
});
},
setIsRoutingVisibileToFalse: () => {
console.log('fired setIsRoutingVisibileToFalse');
setUser({
...user,
isRoutingVisible: false
});
}
}}
>
{children}
</UserContext.Provider>
);
}
export default UserContext;
export { UserProvider };
在路由机中,我这样称呼它:
setUpdateUserMarker({
type: 'updateMarkers',
payload: e.latlng
});