何时从身份验证SwitchNavigator导航?

时间:2019-04-09 21:34:43

标签: react-native redux

我正在我的React Native应用程序中设置身份验证流程,并且我几乎可以使所有工作正常进行,只是我无法弄清楚使用this.props.navigation.navigate("Main");导航到登录堆栈的实际位置。

我的应用程序顶部有一个Switch Navigator,它呈现了auth堆栈(它自己的switch导航)和主堆栈:

// App.js

const AppContainer = createAppContainer(
  createSwitchNavigator({
    Auth: AuthNavigator,
    Main: MainTabNavigator,
  })
);

export default class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <View style={styles.container}>
          <AppContainer />
        </View>
      </Provider>
    );
  }
}

登录屏幕目前是一个完整的虚拟设置(它调用本地api,无论如何成功)。 注意:渲染方法开始时的条件:

// LoginView.js

class LoginView extends Component {
  state =  { username: "", password: "" };

  handleLogin() {
    this.props.login.call(this);
  }

  render() {
    if (this.props.user) {
      this.props.navigation.navigate("Main");
      return null;
    }

    return (
      <View style={styles.container}>
        <Overlay>
          <View style={styles.modalContainer}>
            <DotIndicator color={"darkgrey"} />
            <Text>Logging in...</Text>
          </View>
        </Overlay>

        // ... input components ...
        <Button
          title="Login"
          onPress={this.handleLogin.bind(this)}
        />
      </View>
    );
  }
}

export default connect(
  state => ({
    isLoading: state.auth.isLoading,
    user: state.auth.user,
    error: state.auth.error
  }),
  { login }
)(LoginView);

现在,这在技术上可行,但出现错误Warning: Cannot update during an existing state transition (such as within渲染). Render methods should be a pure function of props and state.

我理解会抛出此错误,因为我正在navigate内部调用render。有道理。

我尝试通过登录操作进行导航:

export function login() {
  return dispatch => {
    dispatch({ type: "LOGIN_START" });
    fetch(url) // this will need to be a POST session (not a GET user)
      .then(res => res.json())
      .then(users => {
        dispatch({ type: "LOGIN_SUCCESS", payload: users[0] });
        console.log("Login succeeded");
        this.props.navigation.navigate("Main");
      })
      .catch(error => {
        console.warn("login failed");
        dispatch({ type: "LOGIN_FAILURE", payload: error });
      });
  };
}

它确实有效,但是在关注点分离方面当然是非常错误的,而且当我尝试使用它来解决登录失败时,这种解决方案还没有真正扩展。

我还考虑过在我的handleLogin()函数(通过登录按钮调用)中进行此操作,无论是否带有async / await:

  async handleLogin() {
    await this.props.login.call(this);
    console.log("Navigating to main screen");
    this.props.navigation.navigate("Main");
  }

但是导航是在操作完成和用户登录之前发生的,这在真实的身份验证流之后当然是不可接受的。 (此外,当我使用async / await进行操作时,“登录成功”将被记录两次!打败我)。确实,我在handleLogin()函数中正在按此方向进行。

navigate通话应该放在哪里?

1 个答案:

答案 0 :(得分:0)

我似乎发现了一些可行的方法,但是它与Redux相距甚远,这使我稍微不舒服。

我已经从Redux操作中提取了所有内容,并将其放在我的LoginView中。我正在Redux方面考虑这一问题,因为程序唯一需要知道的有关授权过程和状态的地方就是授权流程本身(目前为LoginView本身)。商店和应用程序的其余部分唯一需要了解的是用户信息。

因此,我已将Redux login操作替换为简单的assignUser操作。发布状态更改以激活“登录...”叠加层后,我将提取到的performLogin重构为handleLogin

// authActions.js

export function assignUser(user) {
  return dispatch => {
    console.log("user", user);
    dispatch({ type: "LOGIN_SUCCESS", payload: user });
  };
}

// from LoginView.js

  performLogin() {
    fetch("http://127.0.0.1:3000/users") // this will need to be a POST session (not a GET user)
      .then(res => res.json())
      .then(users => {
        console.log("Login succeeded");
        this.props.assignUser(users[0]);
        console.log("Navigating to main screen");
        this.props.navigation.navigate("Main");
      })
      .catch(error => {
        console.warn("login failed", error);
        this.setState({isLoading: false})
      });
  }

  handleLogin() {
    this.setState({ isLoading: true }, this.performLogin);
  }

LoginView组件的其余部分与我的原始帖子相同。

我仍然很想知道是否有人可以通过某种方法来实现这一目标,从而将动作完全保留在Redux中。