Как заменить вложенный стек другим компонентом вact-native-navigation v2? - PullRequest
0 голосов
/ 20 марта 2019

Я пытаюсь создать динамический мастер с реакцией-native-navigation v2.
Я говорю динамический, потому что количество шагов может варьироваться в зависимости от того, какие параметры выбирает пользователь.

Я думал использовать вложенные стеки, поэтому макет моего приложения будет выглядеть примерно так:

{
  root: {
    sideMenu: {
      left: {/*...*/},
      center: {
        stack: {
          children: [component1, /*...,*/ componentX]
        }
      }
    }
  }
}

ComponentX - это место, где я запускаю свой мастер, поэтому я добавляю новый стек следующим образом:

{
// ...
  stack: {
    children: [
      component1,
      //...,
      componentX,
      {
        stack: {
          children: [step1, step2, /*...,*/ stepN]
        }
      }
    ]
  }
}

После того, как пользователь сделает последний выбор на шаге N, я хотел бы заменить вложенный стек сводным экраном, чтобы он выглядел примерно так:

{
//...
  stack: {
    children: [
      component1,
      //...,
      componentX,
      summaryScreen
    ]
  }
}

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

1 Ответ

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

Мне наконец-то удалось это решить.
Вот как:

  1. В начале моего приложения, когда я даю идентификатор для моего основного стека
const sideMenu = {
    left: { /*...*/ },
    center: {
      stack: {
        id: 'main', // this line is important
        children: [/*...*/]
      }
    },
  };
  Navigation.setRoot({
    root: { sideMenu },
  });
  1. Когда я хочу запустить мастер, я добавляю новый стек
Navigation.push(componentId, {
  stack: {
    id: 'wizard',
    children: [
      {
        component: { /*...*/ },
      },
    ],
  }
})
  1. Я нажимаю на экраны в новом стеке wizard по мере продвижения пользователя

  2. Когда я хочу отобразить окончательный итоговый экран, я вызываю setStackRoot для вложенного стека

Navigation.setStackRoot('wizard', [
  {
    component: { /*...*/ },
  },
]);
  1. На этом итоговом экране у меня есть кнопка с надписью «Готово», которая удаляет вложенный стек
Navigation.pop('main');

РЕДАКТИРОВАТЬ: только с этим подходом, если вы нажмете на стрелку назад, когда вы находитесь на вложенном экране, он будет отклонять весь вложенный стек вместо только этого экрана.
Мне пришлось использовать пользовательскую кнопку возврата следующим образом:

Я решил это с помощью пользовательской кнопки возврата: 1. При нажатии на новый экран, где я хочу переопределить кнопку, используйте параметры

import Icon from 'react-native-vector-icons/MaterialIcons';
/* ... */
const backIcon = await Icon.getImageSource('arrow-back', 24, '#000');
const component = {
  id: screenID,
  name: screenID,
  passProps,
  options: {
    topBar: {
      leftButtons: [
        {
          id: 'backButton',
          icon: backIcon,
        },
      ],
    },
  }
};
return Navigation.push(componentId, { component });
  1. Создание HOC для реализации вашего собственного обратного действия
import React, { Component } from 'react';
import { Navigation } from 'react-native-navigation';

const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component';

export default function withCustomBackButton(WrappedComponent) {
  class WithCustomBackButton extends Component {
    componentDidMount() {
      this.navigationEventListener = Navigation.events().bindComponent(this);
    }

    componentWillUnmount() {
      if (this.navigationEventListener) this.navigationEventListener.remove();
    }

    navigationButtonPressed() {
      // Your custom action
      const { componentId } = this.props;
      Navigation.pop(componentId);
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  WithCustomBackButton.displayName = `WithCustomBackButton(${getDisplayName(WrappedComponent)})`;

  return WithCustomBackButton;
}
  1. При регистрации экрана с помощью пользовательской кнопки возврата, оберните его в HOC
import withCustomBackButton from '../components/hoc/WithCustomBackButton';
/* ... */
Navigation.registerComponent('selectLocation', () => withCustomBackButton(SelectLocation));
...