Мое приложение использует 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);
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')}
/>
Вы можете сделать страницу рассылки и разместить там свою логику. Так что просто добавьте 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();
}
}
}
Тогда ваша логика навигации должна сработать после того, как ваша функция входа в систему будет выполнена. Это должно помочь.
render()
пытаются создать новый Scene
.
Key is already defined
и соответствующий код, который использует ваше предложение об использовании componentWillReceiveProps
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript/JS) и его различных диалектах/реализациях (кроме ActionScript). Имейте в виду, что JavaScript — это НЕ то же самое, что Java! Включите все ярлыки, относящиеся к вашему вопросу; например, [node.js], [jQuery], [JSON], [ReactJS], [angular], [ember.js], [vue.js], [typescript], [svelte] и т. д.
<Loading />
, когда приложение React Native еще не подключено к бэкэнду Meteor, и в ситуации, когда пользователь вышел из системы (извне с веб-сайта), он должен быть перенаправлен обратно на<Welcome />
как можно скорее.