Реагирующая навигация - Как передавать данные через разные экраны в TabNavigator? - PullRequest
0 голосов
/ 18 мая 2018

У меня есть TabNavigator, и на каждой вкладке есть StackNavigator.Внутри StackNavigator у меня есть экраны.Экраны в каждой вкладке не вызывают друг друга напрямую;TabNavigator обрабатывает изменения экрана при нажатии вкладки.

На первой вкладке, если пользователь нажимает кнопку, создаются некоторые данные.Если пользователь затем перейдет ко второй вкладке, я хотел бы передать эти данные на экран во второй вкладке.

Вот демонстрационная версия кода:

import React from 'react';
import { Button, Text, View } from 'react-native';
import {
  createBottomTabNavigator,
  createStackNavigator,
} from 'react-navigation';


class HomeScreen extends React.Component {
  doIt = () => {
    this.props.navigation.setParams({results: ['one', 'two']});   // <--- set data when user clicks button.
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        {/* other code from before here */}
        <Button
          title="Set Results"
          onPress={this.doIt}
        />
      </View>
    );
  }
}

class SettingsScreen extends React.Component {
  render() {

    console.log(this.props.navigation);  // <--- console out when user clicks on this tab

    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>Settings</Text>
      </View>
    );
  }
}

const HomeStack = createStackNavigator({
  Home: HomeScreen,
});

const SettingsStack = createStackNavigator({
  Settings: SettingsScreen,
});

export default createBottomTabNavigator(
  {
    Home: HomeStack,
    Settings: SettingsStack,
  },
  {
  }
);

The this.props.navigation.state.params никогда не получает данные results во второй вкладке.Для него даже нет ключа, поэтому, если я попытаюсь получить доступ к this.props.navigation.state.params.results, он будет неопределенным.

Это сбивает с толку, потому что я думал, что props.navigation передается на все экраны автоматически .

Как передать данные с одного экрана на другой через TabNavigator, используя только реагирующую навигацию?Я видел ответы, в которых говорится, что нужно использовать Redux, но я не хотел бы импортировать другую библиотеку, если все, что мне нужно, это сохранять некоторое состояние на разных экранах в разных реагирующих навигаторах.

Ответы [ 4 ]

0 голосов
/ 27 июня 2019

@ tempomax пытался сделать то же самое с AsyncStorage , но данные поступили с задержкой.Иногда вам не нужен Redux, если ваше приложение остается маленьким.

Поэтому попытался найти способ без Redux.Вот что я придумал

Надеюсь, еще не поздно ответить.Решил это с помощью NavigationEvents и установкой params на Маршрут.

Проблема с вкладкой заключается в том, что вы не можете передавать параметры на экран, потому что navigation.navigate будет запускаться автоматическиесли createMaterialTopTabNavigator проведен или нажат на неактивной кнопке TabBar.

Это можно решить с помощью NavigationEvent, как описано ниже.

    import React from 'react';
    import { View } from 'react-native';
    import { NavigationEvents } from 'react-navigation';

    const MyScreen = () => (
      <View>
        <NavigationEvents
          onWillFocus={payload => console.log('will focus',payload)}
          onDidFocus={payload => console.log('did focus',payload)}
          onWillBlur={payload => 
             /*
              if screen is about to change this will be triggred
              In screen 'MyScreen2' you can get it with navigation.params
             */
              this.props.navigation.navigate('MyScreen2', { name: 'Brent' })
          }
          onDidBlur={payload => console.log('did blur',payload)}
        />
        {/* 
          Your view code
        */}
      </View>
    );

    export default MyScreen;

Теперь вы можете получить данные вMyScreen2

 /* 2. Get the param, provide a fallback value if not available */
const { navigation } = this.props;
const itemId = navigation.getParam('name', 'DefaultName');
const otherParam = navigation.getParam('otherParam', 'some default value');
0 голосов
/ 06 июня 2018

Настройка реквизита не работала при передаче данных через разные вкладки.Я даже пытался играть с AsyncStorage, пытаясь сохранить и извлечь их в разных вкладках.

В итоге я использовал Redux для сохранения своих состояний, и до сих пор это работало хорошо.

0 голосов
/ 02 ноября 2018

Я столкнулся с подобной проблемой.У меня была многостраничная форма, на которой клиент настаивал на том, чтобы каждый шаг был заключен во вкладку на панели вкладок.Я использовал навигацию по реагированию createMaterialTopTabNavigator для создания навигатора и не смог найти простой способ передачи данных формы между вкладками.

В итоге я использовал контекстный API реагирования и обернул навигатор по вкладкам вкорневой контейнер формы, который предоставляет значение контекста навигатору и маршрутам внутри.Вот как я это сделал:

Контейнер корневой формы

// MultiScreenForm.js
imports...
import MultiScreenFormNavigator from './MultiScreenFormNavigator'

export const FormContext = React.createContext()

class MultiScreenForm extends Component {
  constructor(props) {
    super(props)
    this.state = {
      // formDataHere
      formUpdaters: {
        onToggleOpIn: this.handleToggleOptIn // example updater method
        // other
      }
  }
  handleToggleOptIn = () => {
    // toggle opt in form data with this.setState
  }

  render() {
    return (
      <FormContext.Provider value={this.state}>
        <MultiScreenFormNavigator />
      </FormContext.Provider>
    )
  }
}

export default MultiScreenForm

Пример страницы формы

// ProfileForm.js
imports...
import { FormContext } from './MultiScreenForm'

class ProfileForm extends Component {
  render() {
    // FormContext.Consumer uses function as child pattern
    return (
      <FormContext.Consumer>
        { (context) => (
             // our form can now use anything that we pass through the context
             // earlier, we passed the root form's state including an updater
             <button onPress={context.formUpdaters.onToggleOptIn} />
             // ...
          )
        }
      </FormContext.Consumer>
    )
  }
}

export default ProfileForm

Вкладка навигатора

// MultiScreenFormNavigator.js
imports...
import ProfileForm from './ProfileForm'
import { createMaterialTopTabNavigator } from 'react-navigation'

const MultiScreenFormNavigator = createMaterialTopTabNavigator(
  {
    Profile: ProfileForm,
    // AnotherForm: AnotherForm
  },
  // { navigator options here... }
)

export default MultiScreenFormNavigator

Мы тогдавизуализировать MultiScreenForm вместо навигатора вкладок напрямую.

Это сработало для меня, но я чувствую, что должен быть более простой способ сделать это.Я надеюсь, что люди, которые читают это, могут поделиться своими подходами.

0 голосов
/ 18 мая 2018

Может показаться, что this.props.navigation.state.params может использовать только один параметр?Возможно?Попробуйте это:

    doIt = () => {
    this.props.navigation.setParams({results: 'one'});   // <--- set data when user clicks button.
  }


console.log(this.props.navigation.state.params.results);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...