In my React Native app, I have a screen which connects to a server to retrieve an access token; when the token is received, I want to show different content.
So far the component for this screen looks like this:
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
is defined like this:
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};
and app-types
is:
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;
}
When I open the screen, the useEffect fires and the token is obtained (I can see it with a console log). Then I assume the dispatch occurs, but the screen doesn't refresh to change from 'No token yet' to 'Got token', as I think it should.
What am I doing wrong here?