Мое приложение использует react-native-router-flux, чтобы решить, какой компонент показывать пользователю, в зависимости от того, является ли пользователь

  • Вход в систему или ожидание подключения приложения к серверной части (показать <Loading />)
  • Выполнен вход (показать <Home />)
  • Вы не вошли в систему (показать <Welcome />)

Какой рекомендуемый способ добиться этого?

Этот пример работает отлично, за исключением того, что он не использует react-native-router-flux. В любом случае изменить код для работы с react-native-router-flux?

В моей попытке ниже вызов Actions.loading() перед вызовом функции render дает ошибку, потому что Actions еще не определены. Можно ли вызывать операторы if после функции render?

Более того, каждый раз, когда реквизиты обновляются, это вызывает повторный рендеринг App, выдавая ошибки о том, как ключи сцены уже существуют.

import React, { Component } from 'react';
import Meteor, { createContainer } from 'react-native-meteor';
import { Actions } from 'react-native-router-flux';

import Home from './components/home';
import Welcome from './components/welcome';
import Loading from './components/loading';
import settings from './config/settings';


Meteor.connect(settings.METEOR_URL);


const App = (props) => {

    const { status, user, loggingIn } = props;

    if (status.connected == false || loggingIn) {
        // Render <Loading />
        Actions.loading();
    } else if (user !== null) {
        // Render <Home />
        Actions.home();
    } else {
        // Render <Welcome />
        Actions.welcome();
    }

    return (
        <Router>
            <Scene key="root">
                <Scene key="home" component={Home} title="Home" hideNavBar={true} />
                <Scene key="welcome" component={Welcome} title="Welcome" hideNavBar={true} />
                <Scene key="loading" component={Loading} title="Loading" hideNavBar={true} />
            </Scene>
        </Router>
    )
}


export default createContainer(() => {
    return {
        status: Meteor.status(),
        user: Meteor.user(),
        loggingIn: Meteor.loggingIn()
    };
}, App)

Проблема с использованием компонента Dispatch

Основываясь на предложении Абейкверди, я создал следующий компонент Dispatch, содержащий логику для отображения одного из компонентов <Loading />, <Home /> или <Welcome />.

Проблема: когда this.props.status.connected равно true (приложение React Native подключается к бэкэнду Meteor), this.props.user всегда на некоторое время перед React Native всегда null. приложение получает эти данные от бэкэнда Meteor. Но поскольку изначально он оценивается как null, Action.welcome() будет выполнен. Такое поведение неверно, когда this.props.user в конечном итоге становится не null через секунду или две, и вместо этого пользователь должен был быть перенаправлен на Actions.home().

Любые идеи?

export class Dispatch extends Component {
    constructor(props) {
        super(props);
    }

    componentWillUpdate() {
        if(this.props.status.connected == false) {
            Actions.loading();
        } else {
            console.log('meteor.user(): ', Meteor.user())
            if (this.props.user !== null) {
                Actions.home();
            } else {
                Actions.welcome();
            }
        }
    }

    render() {
        return (
            <View></View>
        )
    }
}


export default createContainer(() => {
    return {
        status: Meteor.status(),
        user: Meteor.user(),
        loggingIn: Meteor.loggingIn()
    };
}, Dispatch);

Ошибки / предупреждения из журналов react-native log-android

Ниже приведен вывод журнала Android, когда приложение React Native запускается на некоторое время, прежде чем отключать его от сервера Meteor (DDP), убивая сервер Meteor.

Используя console.log("<App /> render"), оказывается, что всякий раз, когда функция render вызывается снова после передачи нового props от Meteor createContainer, возникает ошибка Key is already defined.

В любом случае, чтобы избавиться от этой ошибки / предупреждения?

12-23 02:27:01.875 31197 19338 I ReactNativeJS: Running application "RNapp" with appParams: {"initialProps":{},"rootTag"
:1}. __DEV__ === true, development-level warning are ON, performance optimizations are OFF
12-23 02:27:01.891 31197 19338 I ReactNativeJS: render
12-23 02:27:01.995 31197 19338 I ReactNativeJS: Connected to DDP server.
12-23 02:27:01.999 31197 19338 I ReactNativeJS: Connected to DDP server.
12-23 02:27:02.012 31197 19338 I ReactNativeJS: render
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:02.013 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:34.592 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:34.593 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:34.599 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:34.599 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:34.609 31197 19338 I ReactNativeJS: <Loading /> render
12-23 02:27:35.603 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:35.613 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:35.613 31197 19338 I ReactNativeJS: Key root is already defined!
12-23 02:27:45.599 31197 19338 I ReactNativeJS: Disconnected from DDP server.
12-23 02:27:45.616 31197 19338 I ReactNativeJS: <App /> render
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key home is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key welcome is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key loading is already defined!
12-23 02:27:45.616 31197 19338 I ReactNativeJS: Key root is already defined!

App Компонент

export class App extends Component {

    constructor(props) {
        super(props);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.status.connected == false) {
            Actions.loading();
        } else {
            if (nextProps.user !== null) {
                Actions.home();
            } else {
                Actions.welcome();
            }
        }
    }


    render() {
       console.log('<App /> render')
        return (
            <Router>
                <Scene key="root">
                    <Scene key="home" component={Home} title="Home" hideNavBar={true} />
                    <Scene key="welcome" component={Welcome} title="Welcome" hideNavBar={true} />
                    <Scene key="loading" component={Loading} title="Loading" hideNavBar={true} />
                    <Scene key="profile" component={Profile} title="Home" hideNavBar={true} />
                    <Scene key="history" component={History} title="Home" hideNavBar={true} />
                    <Scene key="search" component={Search} title="Home" hideNavBar={true} />
                </Scene>
            </Router>
        )       
    }

}


export default createContainer(() => {
  return {
    status: Meteor.status(),
    user: Meteor.user(),
    loggingIn: Meteor.loggingIn(),
  };
}, App);
3
Nyxynyx 21 Дек 2016 в 03:57

2 ответа

Вы можете добиться этого, используя начальную опору, вы читаете из хранилища данные, которые будут указывать, вошел ли пользователь в систему или нет, например, с помощью access_token.

Затем вы используете initial = {access_token} // например

Но имейте в виду, что он покажет последнюю сцену с начальным параметром, равным true.

// in componentDidMount
const currentUserAccessToken = store.getState().currentUserAccessToken;
        <Scene
            component={SignIn}
            hideNavBar
            initial={!currentUserAccessToken}
            key="signIn"
            title={I18n.t('sign_in')}
        />
2
Ahmed Ali 21 Дек 2016 в 12:56
Как мы можем обрабатывать отображение компонента <Loading />, когда приложение React Native еще не подключено к бэкэнду Meteor, и в ситуации, когда пользователь вышел из системы (извне с веб-сайта), он должен быть перенаправлен обратно на <Welcome /> как можно скорее.
 – 
Nyxynyx
22 Дек 2016 в 06:17

Вы можете сделать страницу рассылки и разместить там свою логику. Так что просто добавьте Dispatch в качестве сцены и переходите оттуда.

return (
        <Router>
            <Scene key="root">
                <Scene key="dispatch" component={Dispatch} hideNavBar={true} initial={true} />
                <Scene key="home" component={Home} title="Home" hideNavBar={true} />
                <Scene key="welcome" component={Welcome} title="Welcome" hideNavBar={true} />
                <Scene key="loading" component={Loading} title="Loading" hideNavBar={true} />
            </Scene>
        </Router>
    )

Обновление:
Похоже, Метеор передает эти аргументы в реквизиты. После добавления нового реквизита componentWillUpdate() не сработает. Вместо этого вы должны поместить логику навигации через Actions в componentWillReceiveProps(nextProps) следующим образом:

componentWillReceiveProps(nextProps) {
    if(nextProps.status.connected == false) {
        Actions.loading();
    } else {
        console.log('meteor.user(): ', Meteor.user())
        if (this.props.user !== null) {
            Actions.home();
        } else {
            Actions.welcome();
        }
    }
}

Тогда ваша логика навигации должна сработать после того, как ваша функция входа в систему будет выполнена. Это должно помочь.

1
abeikverdi 22 Дек 2016 в 07:17
Обновлен мой вопрос о проблеме, возникшей при использовании страницы отправки.
 – 
Nyxynyx
22 Дек 2016 в 06:15
Понятно. Я обновил ответ на основе вашего обновления. Посмотрим, работает ли это.
 – 
abeikverdi
22 Дек 2016 в 07:17
Спасибо, обновление реквизита не вызывает ошибку о уже существующих ключах сцен? Я думаю, что последующие вызовы render() пытаются создать новый Scene.
 – 
Nyxynyx
22 Дек 2016 в 07:20
Какую именно ошибку вы получаете? Это, вероятно, проблема с маршрутизатором, с которой вы столкнулись.
 – 
abeikverdi
22 Дек 2016 в 11:10
Только что обновленный вопрос с ошибкой Key is already defined и соответствующий код, который использует ваше предложение об использовании componentWillReceiveProps
 – 
Nyxynyx
23 Дек 2016 в 10:30