使用Redux进行Redux导航,一旦通过身份验证即可导航到主屏幕

时间:2018-06-15 11:20:16

标签: authentication react-native redux react-navigation

我知道之前已经问过这个问题,但理想情况下我想保持导航状态存储在react navigation而不是redux中,我最近从React-Native-Router-Flux迁移,我能够调用导航redux动作中的动作本身不像react-navigation

loginUser操作

export const loginUser = ({ email, password }) => {
  return dispatch => {
    dispatch({ type: LOGIN_USER });

    return AuthApi.login(email, password)
      .then(response => {
        return response.json();
      })
      .then(result => {
        if (result.ok) {
          // authenticated successfully
          dispatch(setLoginSuccess(result.auth_token));
          _saveItem("authToken", result.auth_token);
        } else {
          dispatch(setLoginFail(result.message));
        }
      });
  };
};

成功验证后有没有办法调用this.props.navigation.navigate('Home')

导航

const AppStack = createStackNavigator(
  {
    Home: {
      screen: BottomTabNavigator,
      navigationOptions: {
        header: null
      }
    },
    Profile: {
      screen: ProfileScreen,
      navigationOptions: {
        header: null
      }
    },
    Quest: {
      screen: QuestScreen,
      navigationOptions: ({ navigation }) => ({
        title: "Quest Info",
        headerLeft: (
          <HeaderBackButton
            tintColor={"#FFF"}
            onPress={() => navigation.navigate("Home")}
          />
        ),
        headerStyle: {
          backgroundColor: "#E8536D",
          borderBottomColor: "transparent",
          borderBottomWidth: 0,
          elevation: 0,
          shadowOpacity: 0
        },
        headerTitleStyle: {
          fontWeight: "bold",
          color: "#FFF"
        }
      })
    },
    Test: {
      screen: TestScreen,
      navigationOptions: {
        header: null
      }
    }
  },
  {
    initialRouteName: "Home"
  }
);

const AuthStack = createStackNavigator(
  {
    Tutorial: {
      screen: TutorialScreen,
      navigationOptions: {
        header: null
      }
    },
    Login: {
      screen: LoginScreen,
      navigationOptions: {
        header: null
      }
    },
    Register: {
      screen: RegisterScreen,
      navigationOptions: ({ navigation }) => ({
        title: "Sign Up With Email",
        headerLeft: (
          <HeaderBackButton
            tintColor={"#FFF"}
            onPress={() => navigation.navigate("Login")}
          />
        ),
        headerStyle: {
          backgroundColor: "#E8536D",
          borderBottomColor: "transparent",
          borderBottomWidth: 0,
          elevation: 0,
          shadowOpacity: 0
        },
        headerTitleStyle: {
          fontWeight: "bold",
          color: "#FFF"
        }
      })
    },
    ResetPassword: {
      screen: ResetPasswordScreen,
      navigationOptions: ({ navigation }) => ({
        title: "Reset Your Password",
        headerLeft: (
          <HeaderBackButton
            tintColor={"#FFF"}
            onPress={() => navigation.navigate("Login")}
          />
        ),
        headerStyle: {
          backgroundColor: "#E8536D",
          borderBottomColor: "transparent",
          borderBottomWidth: 0,
          elevation: 0,
          shadowOpacity: 0
        },
        headerTitleStyle: {
          fontWeight: "bold",
          color: "#FFF"
        }
      })
    }
  },
  {
    initialRouteName: "Tutorial"
  }
);

export default (RootNavigator = () => {
  return createSwitchNavigator(
    {
      AuthLoading: AuthLoadingScreen,
      App: AppStack,
      Auth: AuthStack
    },
    {
      initialRouteName: "Auth"
    }
  );
});

Auth Reducer

import {
  EMAIL_CHANGED,
  PASSWORD_CHANGED,
  LOGIN_USER,
  LOGIN_USER_SUCCESS,
  LOGIN_USER_FAIL,
  SIGNUP_USER,
  SIGNUP_SUCCESS,
  SIGNUP_FAIL
} from "../actions/types";
const INITIAL_STATE = {
  email: "",
  password: "",
  user: null,
  error: "",
  isAuthenticated: false,
  loading: false,
  Authorization: null
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case EMAIL_CHANGED:
      // returns a new state with ...state by creating a new object
      return { ...state, error: "", email: action.payload };
    case PASSWORD_CHANGED:
      return { ...state, error: "", password: action.payload };
    case LOGIN_USER:
      return { ...state, loading: true, error: "" };
    case LOGIN_USER_SUCCESS:
      return {
        ...state,
        email: "",
        password: "",
        loading: false,
        isAuthenticated: true,
        error: "",
        Authorization: action.payload
      };
    case LOGIN_USER_FAIL:
      return {
        ...state,
        email: "",
        password: "",
        loading: false,
        error: action.payload
      };
    case SIGNUP_USER:
      return { ...state, loading: true, error: "" };
    case SIGNUP_SUCCESS:
      return {
        ...state,
        email: "",
        password: "",
        loading: false,
        isAuthenticated: true,
        Authorization: action.payload,
        error: ""
      };
    case SIGNUP_FAIL:
      return {
        ...state,
        email: "",
        password: "",
        loading: false,
        error: action.payload
      };
    default:
      return state;
  }
};

LoginScreen

loginUser = () => {
  const { email, password } = this.props;
  this.props.loginUser(
    { email, password },
  );
};

componentDidUpdate() {  
  if(this.props.isAuthenticated === true) {
    this.props.navigation.navigate('Home');
  }
};

const mapStateToProps = ({ auth }) => {
  const { email, password, error, loading, isAuthenticated } = auth;

  return { email, password, error, loading, isAuthenticated };
};

export default connect(
  mapStateToProps,
  {
    emailChanged,
    passwordChanged,
    loginUser
  }
)(LoginScreen);

1 个答案:

答案 0 :(得分:2)

是的,我可以使用与您在此处完全相同的方法:带有LoadingScreen,AuthStack和AppStack的SwichtNavigator。

您只需要通过react-redux的connect helper将RegisterScreen连接到redux商店,并使用mapStateToProps挂钩商店的一部分,一旦用户通过屏幕道具验证,将会更新。然后你只需使用componentDidUpdate(),如下所示:

class RegisterScreen extends React.Component {

  ... 

  public componentDidUpdate(): void {

    if (this.props.isAuthenticated === true) {  
      this.props.navigation.navigate('Home');
    }
  }
}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.isAuthenticated // or whatever your state property is called
  };
};

export default connect(mapStateToProps)(RegisterScreen);