React Navigation After Login Navigate Problem
Solution 1:
If you are using mobx for state management, create and manage signedIn state in your mobx state tree. when user logs in , you just have to set signedIn state to true. When user logs out, set signedIn to false. No need to use navigation props. When you change your signedIn state, react-navigation component will rerender.
Solution 2:
From the docs:
It's important to note that when using such a setup, you don't need to manually navigate to the
Home
screen by callingnavigation.navigate('Home')
or any other method. React Navigation will automatically navigate to the correct screen whenisSigned
in changes -Home
screen whenisSignedIn
becomestrue
, and toSignIn
screen whenisSignedIn
becomesfalse
. You'll get an error if you attempt to navigate manually.
https://reactnavigation.org/docs/auth-flow/
So just remove the line:
navigation.navigate('HomeScreen');
And replace it with:
setSignedIn(true)
Or the MobX equivalent if you use MobX.
Solution 3:
You can try like this
return (
<NavigationContainer>
{signedIn != null ? (
<Stack.NavigatorscreenOptions={{headerShown:false}}><Stack.Screenname="HomeScreen"component={_homeScreen} /></Stack.Navigator>
) : (
<Stack.NavigatorscreenOptions={{headerShown:false}}><Stack.Screenname="WelcomeScreen"component={_welcomeScreen} /><Stack.Screenname="RegisterScreen"component={_registerScreen} /><Stack.Screenname="LoginScreen"component={_loginScreen} /><Stack.Screenname="ForgotScreen"component={_forgotScreen} /><Stack.Screenname="EmailCodeScreen"component={_emailCodeScreen} /></Stack.Navigator>
)}
</NavigationContainer>
);
Solution 4:
First of all you cant use NavigationContainer twice..I would suggest make two Navigator like this one Login and another AppStack like this! I would just use redux and redux persist with async storage,makes life easier
constApp = () => {
useEffect(() => {
setTimeout(() => {
RNBootSplash.hide({fade: true});
}, 1000);
}, []);
constLoginStack = () => {
return (
<Stack.Navigator><Stack.Screenname="Login"component={Login}options={{headerTransparent:true,
cardStyle: {backgroundColor:colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/><Stack.Screenname="Terms"component={Terms}options={{headerTransparent:true,
cardStyle: {backgroundColor:colors.BACKGROUND},
...TransitionPresets.ModalPresentationIOS,
headerTitleStyle: {color: 'transparent'},
}}
/></Stack.Navigator>
);
};
constAppStack = () => {
return (
<Stack.Navigator>
{screens.map((screen, i) => (
<Stack.Screenname={screen.name}component={screen.screenname}key={i}options={{headerTransparent:true,
cardStyle: {backgroundColor:colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
))}
</Stack.Navigator>
);
};
constAppState = () => {
const checkLoggedIn = useSelector((state) => state.AuthReducer.loggedIn);
return<>{checkLoggedIn === false ? <LoginStack /> : <AppStack />}</>;
};
return (
<Providerstore={store}><NavigationContainer><AppState /></NavigationContainer></Provider>
);
};
store.js
import {applyMiddleware, createStore} from'redux';
import thunk from'redux-thunk';
importAsyncStoragefrom'@react-native-async-storage/async-storage';
import {persistStore, persistReducer} from'redux-persist';
import rootReducer from'./index';
// Middleware: Redux Persist Configconst persistConfig = {
// Rootkey: 'root',
// Storage Method (React Native)storage: AsyncStorage,
// Whitelist (Save Specific Reducers)whitelist: ['StickerReducer', 'AuthReducer'],
// Blacklist (Don't Save Specific Reducers)blacklist: [''],
};
// Middleware: Redux Persist Persisted Reducerconst persistedReducer = persistReducer(persistConfig, rootReducer);
const middleware = [thunk];
const store = createStore(persistedReducer, applyMiddleware(...middleware));
// Middleware: Redux Persist Persisterlet persistor = persistStore(store);
// Exportsexport {store, persistor};
Auth Reducer
import {ADD_DEVICE_TOEKN, LOGGED_IN} from'./types';
const initialState = {
loggedIn: false,
user_Id: '',
device_token: '',
};
exportdefaultAuthReducer = (state = initialState, action) => {
switch (action.type) {
caseLOGGED_IN:
const paylodLoggedIn = action.payload;
return {
...state,
loggedIn: paylodLoggedIn.loggedIn,
user_Id: paylodLoggedIn.loggedIn,
};
caseADD_DEVICE_TOEKN:
const paylodToken = action.payload;
return {
...state,
device_token: paylodToken,
};
default:
return state;
}
};
import {combineReducers} from'redux';
importAuthReducerfrom'./AuthReducer';
importStickerReducerfrom'./StickerReducer';
exportdefaultcombineReducers({
AuthReducer: AuthReducer,
StickerReducer: StickerReducer,
});
Authaction.js
import {LOGGED_IN} from'../types';
exportconstLoginAction = (userData) => {
return(dispatch) => {
dispatch({
type: LOGGED_IN,
payload: userData,
});
};
};
Finally login dispacther
import {useDispatch} from'react-redux';
import {LoginAction} from'../../../redux/actions/LoginAction';
constLogin = ({navigation}) => {
const dispatch = useDispatch();
return (
<PressableonPress={() =>dispatch(LoginAction(data))}>
</Pressable>
);
};
Solution 5:
If you wanna trigger the App.js after successfull login ... then You need to wrap your NavigationContainer with React.Context
Your signedIn
user is an object
I think ... not an array
so by initalizing it in state with []
... if(signedIn != null)
will never evaluate to true
++ Make sure you JSON.parse
your object after fetching it from AsyncStorage
...
constAuthContext = React.createContext({
signedIn,
_checkUser: () => {},
});
exportconstuseAuth = () => React.useContext(AuthContext);
const defaultValue = {
signedIn,
_checkUser,
};
return (
<AuthContext.Providervalue={defaultValue}><NavigationContainer><Stack.NavigatorscreenOptions={{headerShown:false }}>
{signedIn ? (
<Stack.Screenname="HomeScreen"component={_homeScreen} />
) : (
<><Stack.Screenname="WelcomeScreen"component={_welcomeScreen} /><Stack.Screenname="RegisterScreen"component={_registerScreen} /><Stack.Screenname="LoginScreen"component={_loginScreen} /><Stack.Screenname="ForgotScreen"component={_forgotScreen} /><Stack.Screenname="EmailCodeScreen"component={_emailCodeScreen}
/></>
)}
</Stack.Navigator></NavigationContainer>
</AuthContext.Provider>
);
In LoginScreen
// Then you refresh you auth user in LoginScreen likeconst { _checkUser } = useAuth();
_checkUser();
Post a Comment for "React Navigation After Login Navigate Problem"