React Context: Error: userState must be used within a UserProvider despite nested in Provider?
React Context: Error: userState must be used within a UserProvider despite nested in Provider?
我正在关注 Kent C. Dodds 关于 React Context 用法的精彩 tut。
但我实际上将此组件嵌套在提供程序中,所以不确定我为什么会收到。
Error: userState must be used within a UserProvider
所以也许我没有明白创建一个抛出错误的函数的意义,尽管遵循了您应该如何使用提供程序...也许我实施不正确?
所以这是我的 userContext 设置:
import React, { useState, useEffect, useContext, useReducer } from 'react';
var initialState = {
...state...
};
var UserStateContext = React.createContext();
var UserContextDispatch = React.createContext();
function setLocalStorage(key, value) {
...function innards...
}
function getLocalStorage(key, initialValue) {
...function innards...
}
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 'addMarker': {
user.isLengthOfMarkersLessThanTwo
? {
...state,
markers: user.markers.concat(payload.marker)
}
: null;
break;
}
case 'setMap': {
return {
...state,
currentMap: payload.curerntMap
};
}
default: {
throw new Error(`Unhandled action type: ${type}`);
}
}
}
const [user, setUser] = useState(() => getLocalStorage('user', initialState));
var [state, dispatch] = useReducer(userReducer, user);
useEffect(() => {
setLocalStorage('user', state);
}, [state]);
return (
<UserStateContext.Provider value={state}>
<UserContextDispatch.Provider value={dispatch}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);
}
function userState() {
const context = React.useContext(UserStateContext);
if (context === undefined) {
throw new Error('userState must be used within a UserProvider');
}
return context;
}
function userDispatch() {
const context = React.useContext(UserContextDispatch);
if (context === undefined) {
throw new Error('userDispatch must be used within a UserProvider');
}
return context;
}
export { UserProvider, userState, userDispatch };
错误指向我的地图组件,它正在将 state
和 dispatch
属性从 UserContext
传递到我的路由组件,这是一个 class 组件。
import React, { useState, useContext, useEffect, useRef, useCallback } from 'react';
import { Button } from 'semantic-ui-react';
import L from 'leaflet';
import * as ELG from 'esri-leaflet-geocoder';
import { Map } from 'react-leaflet';
import { Dimmer, Loader } from 'semantic-ui-react';
import Routing from '../RoutingMachine/RoutingMachine.jsx';
import { userState, userDispatch } from '../Context/UserContext.jsx';
import UIContext from '../Context/UIContext.jsx';
import { stringify } from 'flatted';
export default function MyMap({}) {
var [zoom, setZoom] = useState(18);
var [animate, setAnimate] = useState(false);
var [userLocation, setUserLocation] = useState(null);
var mapRef = useRef();
console.log('userState() ', userState());
var {
avatar,
currentMap,
id,
isLengthOfMarkersLessThanTwo,
isRoutingVisible,
markers,
removeRoutingMachine
} = userState();
var dispatch = userDispatch();
var { isMobile, isDesktop } = useContext(UIContext);
useEffect(() => {
if (isRoutingVisible === false) {
dispatch({
type: 'setIsRoutingVisible',
payload: {
isRoutingVisible: true
}
});
}
});
useEffect(() => {
if (markers.length === 2) {
dispatch({
type: 'isLengthOfMarkersLessThanTwoFalse',
payload: { isLengthOfMarkersLessThanTwo: false }
});
}
}, [JSON.stringify(markers)]);
return (
<Map
animate={animate}
onLocationFound={handleOnLocationFound}
zoom={zoom}
ref={mapRef}
>
{isRoutingVisible && (
<Routing
markers={markers}
dispatch={dispatch}
removeRoutingMachine={removeRoutingMachine}
map={currentMap}
userLocation={userLocation}
isMobile={isMobile}
isDesktop={isDesktop}
/>
)}
</Map>
);
}
问题似乎出在我将 state
和 dispatch
值传递给每个提供商的方式:
return (
<UserStateContext.Provider value={state}>
<UserContextDispatch.Provider value={dispatch}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);
我通过传递一个值为以下的对象来让它工作:value={{ key: value }}
所以应该这样做:
return (
<UserStateContext.Provider value={{ state: state }}>
<UserContextDispatch.Provider value={{ dispatch: dispatch }}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);
我正在关注 Kent C. Dodds 关于 React Context 用法的精彩 tut。
但我实际上将此组件嵌套在提供程序中,所以不确定我为什么会收到。
Error: userState must be used within a UserProvider
所以也许我没有明白创建一个抛出错误的函数的意义,尽管遵循了您应该如何使用提供程序...也许我实施不正确?
所以这是我的 userContext 设置:
import React, { useState, useEffect, useContext, useReducer } from 'react';
var initialState = {
...state...
};
var UserStateContext = React.createContext();
var UserContextDispatch = React.createContext();
function setLocalStorage(key, value) {
...function innards...
}
function getLocalStorage(key, initialValue) {
...function innards...
}
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 'addMarker': {
user.isLengthOfMarkersLessThanTwo
? {
...state,
markers: user.markers.concat(payload.marker)
}
: null;
break;
}
case 'setMap': {
return {
...state,
currentMap: payload.curerntMap
};
}
default: {
throw new Error(`Unhandled action type: ${type}`);
}
}
}
const [user, setUser] = useState(() => getLocalStorage('user', initialState));
var [state, dispatch] = useReducer(userReducer, user);
useEffect(() => {
setLocalStorage('user', state);
}, [state]);
return (
<UserStateContext.Provider value={state}>
<UserContextDispatch.Provider value={dispatch}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);
}
function userState() {
const context = React.useContext(UserStateContext);
if (context === undefined) {
throw new Error('userState must be used within a UserProvider');
}
return context;
}
function userDispatch() {
const context = React.useContext(UserContextDispatch);
if (context === undefined) {
throw new Error('userDispatch must be used within a UserProvider');
}
return context;
}
export { UserProvider, userState, userDispatch };
错误指向我的地图组件,它正在将 state
和 dispatch
属性从 UserContext
传递到我的路由组件,这是一个 class 组件。
import React, { useState, useContext, useEffect, useRef, useCallback } from 'react';
import { Button } from 'semantic-ui-react';
import L from 'leaflet';
import * as ELG from 'esri-leaflet-geocoder';
import { Map } from 'react-leaflet';
import { Dimmer, Loader } from 'semantic-ui-react';
import Routing from '../RoutingMachine/RoutingMachine.jsx';
import { userState, userDispatch } from '../Context/UserContext.jsx';
import UIContext from '../Context/UIContext.jsx';
import { stringify } from 'flatted';
export default function MyMap({}) {
var [zoom, setZoom] = useState(18);
var [animate, setAnimate] = useState(false);
var [userLocation, setUserLocation] = useState(null);
var mapRef = useRef();
console.log('userState() ', userState());
var {
avatar,
currentMap,
id,
isLengthOfMarkersLessThanTwo,
isRoutingVisible,
markers,
removeRoutingMachine
} = userState();
var dispatch = userDispatch();
var { isMobile, isDesktop } = useContext(UIContext);
useEffect(() => {
if (isRoutingVisible === false) {
dispatch({
type: 'setIsRoutingVisible',
payload: {
isRoutingVisible: true
}
});
}
});
useEffect(() => {
if (markers.length === 2) {
dispatch({
type: 'isLengthOfMarkersLessThanTwoFalse',
payload: { isLengthOfMarkersLessThanTwo: false }
});
}
}, [JSON.stringify(markers)]);
return (
<Map
animate={animate}
onLocationFound={handleOnLocationFound}
zoom={zoom}
ref={mapRef}
>
{isRoutingVisible && (
<Routing
markers={markers}
dispatch={dispatch}
removeRoutingMachine={removeRoutingMachine}
map={currentMap}
userLocation={userLocation}
isMobile={isMobile}
isDesktop={isDesktop}
/>
)}
</Map>
);
}
问题似乎出在我将 state
和 dispatch
值传递给每个提供商的方式:
return (
<UserStateContext.Provider value={state}>
<UserContextDispatch.Provider value={dispatch}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);
我通过传递一个值为以下的对象来让它工作:value={{ key: value }}
所以应该这样做:
return (
<UserStateContext.Provider value={{ state: state }}>
<UserContextDispatch.Provider value={{ dispatch: dispatch }}>
{children}
</UserContextDispatch.Provider>
</UserStateContext.Provider>
);