[英]React Navigation after login navigate problem
我在 React Navigation 中使用 useNavigation。 用AsyncStorage登錄后,想重定向到首頁,但是不能go回到App function。 當我想 go 到主頁時,導航找不到它並返回錯誤。
如何觸發 function 命名的應用程序?
導航錯誤(控制台)
帶有有效負載 {"name":"HomeScreen"} 的操作 'NAVIGATE' 未被任何導航器處理
登錄代碼
await AsyncStorage.setItem("userData", JSON.stringify(data.data));
navigation.navigate('HomeScreen');
應用程序.js
const App = () => {
const [signedIn, setSignedIn] = useState([]);
useEffect(() => {
_checkUser();
}, []);
async function _checkUser(){
let responseUser = await AsyncStorage.getItem("userData");
setSignedIn(responseUser);
}
if(signedIn != null) {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="HomeScreen" component={_homeScreen} />
</Stack.Navigator>
</NavigationContainer>
)
} else {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
}
當我嘗試用 MOBX..
let signedIn = userStore.isLogin;
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
{
signedIn ? (
<Stack.Screen name="HomeScreen" component={_homeScreen} />
) : (
<>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
)
路由器
let data = await axios.post(baseURL+"users_checkMail", sendData);
uaStore.userStore.userData = data.data;
uaStore.userStore.isLogin = true;
await AsyncStorage.setItem("userData", JSON.stringify(data.data));
console.log(userStore.isLogin); // LOG: TRUE
setLoader(false);
navigation.navigate('HomeScreen');
如果您使用 mobx 進行 state 管理,請在您的 mobx state 樹中創建和管理 signedIn state。 當用戶登錄時,您只需將 signedIn state 設置為 true。 當用戶注銷時,將 signedIn 設置為 false。 無需使用導航道具。 當您更改您的已簽名 state 時,react-navigation 組件將重新呈現。
如果你想在成功登錄后觸發 App.js... 那么你需要用React.Context包裝你的 NavigationContainer
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它來自AsyncStorage
...
const AuthContext = React.createContext({
signedIn,
_checkUser: () => {},
});
export const useAuth = () => React.useContext(AuthContext);
const defaultValue = {
signedIn,
_checkUser,
};
return (
<AuthContext.Provider value={defaultValue}>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
{signedIn ? (
<Stack.Screen name="HomeScreen" component={_homeScreen} />
) : (
<>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen
name="EmailCodeScreen"
component={_emailCodeScreen}
/>
</>
)}
</Stack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
在登錄屏幕中
// Then you refresh you auth user in LoginScreen like
const { _checkUser } = useAuth();
_checkUser();
你可以這樣嘗試
return (
<NavigationContainer>
{signedIn != null ? (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="HomeScreen" component={_homeScreen} />
</Stack.Navigator>
) : (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
);
首先你不能使用 NavigationContainer 兩次..我建議讓兩個 Navigator 這樣一個 Login 和另一個 AppStack 這樣,我只會使用 redux 和 redux 堅持異步存儲,讓生活更輕松
const App = () => {
useEffect(() => {
setTimeout(() => {
RNBootSplash.hide({fade: true});
}, 1000);
}, []);
const LoginStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Login"
component={Login}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
<Stack.Screen
name="Terms"
component={Terms}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalPresentationIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
</Stack.Navigator>
);
};
const AppStack = () => {
return (
<Stack.Navigator>
{screens.map((screen, i) => (
<Stack.Screen
name={screen.name}
component={screen.screenname}
key={i}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
))}
</Stack.Navigator>
);
};
const AppState = () => {
const checkLoggedIn = useSelector((state) => state.AuthReducer.loggedIn);
return <>{checkLoggedIn === false ? <LoginStack /> : <AppStack />}</>;
};
return (
<Provider store={store}>
<NavigationContainer>
<AppState />
</NavigationContainer>
</Provider>
);
};
store.js
import {applyMiddleware, createStore} from 'redux';
import thunk from 'redux-thunk';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {persistStore, persistReducer} from 'redux-persist';
import rootReducer from './index';
// Middleware: Redux Persist Config
const persistConfig = {
// Root
key: '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 Reducer
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middleware = [thunk];
const store = createStore(persistedReducer, applyMiddleware(...middleware));
// Middleware: Redux Persist Persister
let persistor = persistStore(store);
// Exports
export {store, persistor};
授權減速器
import {ADD_DEVICE_TOEKN, LOGGED_IN} from './types';
const initialState = {
loggedIn: false,
user_Id: '',
device_token: '',
};
export default AuthReducer = (state = initialState, action) => {
switch (action.type) {
case LOGGED_IN:
const paylodLoggedIn = action.payload;
return {
...state,
loggedIn: paylodLoggedIn.loggedIn,
user_Id: paylodLoggedIn.loggedIn,
};
case ADD_DEVICE_TOEKN:
const paylodToken = action.payload;
return {
...state,
device_token: paylodToken,
};
default:
return state;
}
};
import {combineReducers} from 'redux';
import AuthReducer from './AuthReducer';
import StickerReducer from './StickerReducer';
export default combineReducers({
AuthReducer: AuthReducer,
StickerReducer: StickerReducer,
});
Authaction.js
import {LOGGED_IN} from '../types';
export const LoginAction = (userData) => {
return (dispatch) => {
dispatch({
type: LOGGED_IN,
payload: userData,
});
};
};
最后登錄dispatcher
import {useDispatch} from 'react-redux';
import {LoginAction} from '../../../redux/actions/LoginAction';
const Login = ({navigation}) => {
const dispatch = useDispatch();
return (
<Pressable onPress={() =>dispatch(LoginAction(data))}>
</Pressable>
);
};
從文檔:
請務必注意,在使用此類設置時,您無需通過調用
navigation.navigate('Home')
或任何其他方法手動導航到Home
屏幕。 當isSigned
in 更改時,React Navigation 將自動導航到正確的屏幕- 當isSignedIn
變為true
時,Home
屏幕,當isSignedIn
變為false
時,導航到SignIn
屏幕。 如果您嘗試手動導航,則會收到錯誤消息。
https://reactnavigation.org/docs/auth-flow/
所以只需刪除該行:
navigation.navigate('HomeScreen');
並將其替換為:
setSignedIn(true)
或者如果您使用 MobX,則使用 MobX 等價物。
我在嘗試使用 useNavigation 鈎子時遇到了同樣的錯誤......我能夠使用調度方法解決它......
import { CommonActions } from '@react-navigation/native';
navigation.dispatch(
CommonActions.navigate({ name: 'Profile', params: { user: 'jane' }})
);
我創建了一個實用程序 function 以減少重復...
const handleNavigate = (key: string) => {
navigation.dispatch(CommonActions.navigate({ name: key }));
};
// Usage
handleNavigate("Home")
這為我擺脫了錯誤。 希望這可以幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.