调度程序似乎没有从上下文中调度状态
Dispatcher does not seem to dispatch state from context
在我的 React Native 应用程序中,我有一个连接到服务器以检索访问令牌的屏幕;收到令牌后,我想显示不同的内容。
到目前为止,此屏幕的组件如下所示:
import {AppContext} from './stores/app-context';
import api from '../../api/api';
const MyScreen = () => {
const {state, dispatch} = React.useContext(AppContext);
const {appToken} = state;
// On opening the screen, get an access token
useEffect(() => {
const getToken = async () => {
try {
const url = 'url goes here';
// This should get the token and return it in response.accessToken
// If the token request is rejected, response.accessToken is null
const response = await api.getData(`${url}`, {
headers: {Accept: 'application/json'},
});
response.accessToken
? dispatch({
type: 'setToken',
newToken: response.accessToken,
})
: dispatch({
type: 'setError',
text: 'Unable to obtain a token',
});
} catch (error) {
console.log('Error: ', error);
}
};
getToken();
}, []);
if (appToken) {
return <View>Got the token</View>;
}
return <View>No token yet</View>;
};
export default MyScreen;
AppContext
定义如下:
import {AppReducer} from './app-reducer';
import {IAppAction, IAppState} from './app-types';
let initialState: IAppState = {
appToken: null,
errorMessage: null,
};
const AppContext = createContext<{
state: IAppState;
dispatch: React.Dispatch<IAppAction>;
}>({
state: initialState,
dispatch: () => null,
});
const AppProvider = ({children}: any) => {
const [state, dispatch] = useReducer(AppReducer, initialState);
return (
<AppContext.Provider value={{state, dispatch}}>
{children}
</AppContext.Provider>
);
};
export {AppContext, AppProvider};
`AppReducer` is:
import {IAppAction, IAppState} from './app-types';
const AppReducer = (state: IAppState, action: IAppAction) => {
switch (action.type) {
case 'setError':
if (action.text) {
return {
...state,
errorMessage: action.text,
};
}
case 'setToken':
if (action.newToken) {
return {
...state,
appToken: action.newToken,
};
}
break;
default:
throw new Error();
}
return {...state};
};
export {AppReducer};
和app-types
是:
export interface IAppState {
appToken: null | string;
errorMessage: null | string;
}
export type Action = 'setToken' | 'setError';
export interface IAppAction {
type: Action;
newToken?: null | string;
text?: null | string;
}
当我打开屏幕时,useEffect 会触发并获得令牌(我可以通过控制台日志看到它)。然后我假设调度发生了,但屏幕没有刷新以从 'No token yet' 更改为 'Got token',正如我认为的那样。
我做错了什么?
我一直在阅读您的代码,我只能说确保您已将 MyScreen
包裹在 AppProvider
中,就像这样:
<AppProvider>
<MyScreen/>
</AppProvider>
查看 code sandbox。
确保有 AppProvider 并且 api returns 格式正确。
在我的 React Native 应用程序中,我有一个连接到服务器以检索访问令牌的屏幕;收到令牌后,我想显示不同的内容。
到目前为止,此屏幕的组件如下所示:
import {AppContext} from './stores/app-context';
import api from '../../api/api';
const MyScreen = () => {
const {state, dispatch} = React.useContext(AppContext);
const {appToken} = state;
// On opening the screen, get an access token
useEffect(() => {
const getToken = async () => {
try {
const url = 'url goes here';
// This should get the token and return it in response.accessToken
// If the token request is rejected, response.accessToken is null
const response = await api.getData(`${url}`, {
headers: {Accept: 'application/json'},
});
response.accessToken
? dispatch({
type: 'setToken',
newToken: response.accessToken,
})
: dispatch({
type: 'setError',
text: 'Unable to obtain a token',
});
} catch (error) {
console.log('Error: ', error);
}
};
getToken();
}, []);
if (appToken) {
return <View>Got the token</View>;
}
return <View>No token yet</View>;
};
export default MyScreen;
AppContext
定义如下:
import {AppReducer} from './app-reducer';
import {IAppAction, IAppState} from './app-types';
let initialState: IAppState = {
appToken: null,
errorMessage: null,
};
const AppContext = createContext<{
state: IAppState;
dispatch: React.Dispatch<IAppAction>;
}>({
state: initialState,
dispatch: () => null,
});
const AppProvider = ({children}: any) => {
const [state, dispatch] = useReducer(AppReducer, initialState);
return (
<AppContext.Provider value={{state, dispatch}}>
{children}
</AppContext.Provider>
);
};
export {AppContext, AppProvider};
`AppReducer` is:
import {IAppAction, IAppState} from './app-types';
const AppReducer = (state: IAppState, action: IAppAction) => {
switch (action.type) {
case 'setError':
if (action.text) {
return {
...state,
errorMessage: action.text,
};
}
case 'setToken':
if (action.newToken) {
return {
...state,
appToken: action.newToken,
};
}
break;
default:
throw new Error();
}
return {...state};
};
export {AppReducer};
和app-types
是:
export interface IAppState {
appToken: null | string;
errorMessage: null | string;
}
export type Action = 'setToken' | 'setError';
export interface IAppAction {
type: Action;
newToken?: null | string;
text?: null | string;
}
当我打开屏幕时,useEffect 会触发并获得令牌(我可以通过控制台日志看到它)。然后我假设调度发生了,但屏幕没有刷新以从 'No token yet' 更改为 'Got token',正如我认为的那样。
我做错了什么?
我一直在阅读您的代码,我只能说确保您已将 MyScreen
包裹在 AppProvider
中,就像这样:
<AppProvider>
<MyScreen/>
</AppProvider>
查看 code sandbox。
确保有 AppProvider 并且 api returns 格式正确。