Когда переходить из аутентификации SwitchNavigator? - PullRequest
0 голосов
/ 10 апреля 2019

Я настраиваю поток аутентификации в своем приложении React Native, и я в значительной степени могу заставить все работать, кроме того, что я не могу определить фактическое правильное место, чтобы перейти к стеку входа в систему с помощью this.props.navigation.navigate("Main");.

У меня в верхней части моего приложения есть Навигатор коммутаторов, отображающий стек авторизации (собственный переключатель 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, «Login Succeeded» регистрируется дважды! Ударяет меня).Такое ощущение, что я на правильном пути, выполняя это в своей функции handleLogin().

Куда мне направить мой вызов navigate?

1 Ответ

0 голосов
/ 10 апреля 2019

Я, кажется, нашел что-то, что работает, но это отходит от 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...