簡體   English   中英

登錄導航問題后反應導航

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM