web-dev-qa-db-ja.com

反応ナビゲーションで異なるネストされたスタック間を移動する方法

目標

反応ナビゲーションを使用して、ナビゲーターの画面から別のナビゲーターの画面に移動します。

より詳しく

次のナビゲーター構造がある場合:

  • 親ナビゲーター
    • ネストされたナビゲーター1
      • 画面A
      • 画面B
    • 入れ子のナビゲーター2
      • 画面C
      • 画面D

ネストされたナビゲーター2の画面Dからネストされたナビゲーター1の画面Aに移動するにはどうすればよいですか?今のところ、画面Dから画面Aにnavigation.navigateを行おうとすると、画面Aについては知らず、画面CとDのみが認識されるというエラーが表示されます。

GitHub( https://github.com/react-navigation/react-navigation/issues/983https://github.com/react-navigation/react-navigation/issues/335#issuecomment-280686611 )しかし、非常に基本的なもののために、明確な欠如があります答えを探して、何百ものGitHubのコメントをスクロールして解決策を検索するのはよくありません。

たぶん、この質問は、この非常に一般的な問題に直面しているすべての人のためにこれを行う方法を成文化することができます。

23
izikandrw

navigateの3番目のパラメーター を使用して、特定のサブアクションを実行できます。

たとえば、ネストされたナビゲータ2の画面Dからネストされたナビゲータ1の画面Aに移動する場合:

this.props.navigation.navigate('NestedNavigator1', {}, NavigationActions.navigate({ routeName: 'screenB' }))

また、ネストされたナビゲーターを使用している場合は、 よくある間違い を確認してください。

26
Stackia

React Navigation v3:

Navigation.navigateは、パラメータとして1つのオブジェクトを取ります。スタック名を設定し、次のようにそのスタック内のルートに移動します...

navigation.navigate(NavigationActions.navigate({
    routeName: 'YOUR_STACK',
    action: NavigationActions.navigate({ routeName: 'YOUR_STACK-subRoute' })
}))

「YOUR_STACK」は、作成時にスタックが呼び出されるものです...

  YOUR_STACK: createStackNavigator({ subRoute: ... })
13
Phil Andrews

完全な自由:ナビゲーションオプション付きのシングルトン

複数のナビゲーションスタックとサブスタックがある場合、React Navigationのセットアップ方法を考えると、目的のスタックへの参照を取得する方法がわからずにイライラする可能性があります。特定のスタックをいつでも簡単に参照できれば、これははるかに簡単です。方法は次のとおりです。

  1. どこでも参照したいスタックに固有のシングルトンを作成します。

    // drawerNavigator.js . (or stackWhatever.js)
    const nav = {}
    export default {
      setRef: ref => nav.ref = ref,
      getRef: () => nav.ref
    }
    
  2. NavigatorOptionsを使用して、目的のナビゲーターの参照を設定します

    import { createBottomTabNavigator } from 'react-navigation'
    import drawerNavigation from '../drawerNavigator'
    
    const TabNavigation = createBottomTabNavigator(
      {
        // screens listed here
      },
      {
        navigationOptions: ({ navigation }) => {
          // !!! secret sauce set a reference to parent
          drawerNavigation.setRef(navigation)
          return {
            // put navigation options
          }
        }
      }
    )
    
  3. これで、drawerNavigatorの内部または外部のどこでも参照できます

    // screen.js
    import drawerNavigator from '../drawerNavigator'
    
    export default class Screen extends React.Component {
      render() {
        return (
          <View>
            <TouchableHighlight onPress={() => drawerNavigator.getRef().openDrawer()}>
              <Text>Open Drawer</Text>
            </TouchableHighlight>
          </View>
        )
      }
    }
    

説明

ステップ2では、タブナビゲーターはドロワーナビゲーター内の画面の1つです。 Tab Navigatorはドロワーを閉じる必要がありますが、アプリ内の任意の場所でも閉じる必要があります。このステップの実行後にdrawerNavigator.getRef().closeDrawer()を呼び出すことができます。そのステップの後、props.navigationに直接アクセスすることに限定されません。

1
Jason Sebring

私もそのような解決策を見つけました here

onPress={() =>
    Promise.all([
    navigation.dispatch(
        NavigationActions.reset({
            index: 0,
            // TabNav is a TabNavigator nested in a StackNavigator
            actions: [NavigationActions.navigate({ routeName: 'TabNav' })]
        })
    )
    ]).then(() => navigation.navigate('specificScreen'))
}
0
Aliaksei

私の目標は、通常のスタック遷移を使用して、認証画面がすべて同じ背景とアプリの残りの部分を共有することでした。

数時間後、解決策はコンポーネントラッパーと同じファイルにcreateStackNavigator()を含めることであることがわかりました。 static routerdocument のように正常に公開できるようにします。これにより、You should only render one navigator explicitly in your app警告が回避され、this.props.navigation.navigate('AnyScreen')を使用してネストされた画面に移動できます。

AuthRouter.js

export const AuthNavigationStack = createStackNavigator(
  {
    Login: {
      screen: Login
    },
    CreateAccount: {
      screen: CreateAccount
    }
  }
);

export default class AuthContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = AuthNavigationStack.router;

  render() {
    return (
      <ImageBackground
        style={ {
          width: '100%',
          height: '100%'
        } }
        source={ require( '../Images/johannes-andersson-yosimite.jpg' ) }
        blurRadius={ 10 }
      >
        <StatusBar
          barStyle="dark-content"
          backgroundColor="transparent"
          translucent={ true }
        />
        <AuthNavigationStack navigation={ this.props.navigation } />
      </ImageBackground>
    );
  }
}

MessengerRouter.js

export const MessengerStackNavigator = createStackNavigator(
  {
    Chat: {
      screen: Chat,
    },
    User: {
      screen: User,
    },
  }
);

export default class MainContainer extends React.Component {
  constructor( props ) {
    super( props );
  }

  static router = MessengerStackNavigator.router;

  render() {
    return <MessengerStackNavigator navigation={ this.props.navigation } />;
  }
}

Router.js

import { createStackNavigator } from 'react-navigation';

import AuthRouter from './AuthRouter';
import MessengerRouter from './MessengerRouter';

export const RootNavigationStack = createStackNavigator( {
  AuthContainer: {
    screen: AuthRouter,
    navigationOptions: () => ( {
      header: null
    } )
  },
  MessengerRouter: {
    screen: MessengerRouter,
    navigationOptions: () => ( {
      header: null
    } )
  }
} );

RootContainer.js

import { RootNavigationStack } from '../Config/Router';

class RootContainer extends Component {

  render() {
    return <RootNavigationStack />;
  }
}

ノート:

  • header: nullRootNaviagtionStackからネストされたスタックに渡して、重複するヘッダーを削除します

  • Nested AからNested Bに移動して戻るボタンを使用すると、Nested Bの最初の画面に戻ります。大きな問題ではありませんが、修正方法がわかりません。

0
Son Le
 const subAction = NavigationActions.navigate({ routeName: 'SignInScreen' });
      AsyncStorage.clear().then(() =>
        this.props.navigation.navigate('LoggedOut', {}, subAction));

LoggedOutは、signIn画面が配置されるスタック名です。

0
Rishav Kumar

反応ネイティブのプロジェクトに取り組んでいるときに、同じ状況に遭遇しました。画面への移動に複数の方法を試しましたが、失敗しました。

多くの試行の後、私は親ナビゲーションオブジェクトを子に渡し、ナビゲーション関数を呼び出してみました。

ここで問題になります。画面Dから画面Aに移動する場合は、次の手順に従ってください。

-> screenPropsを使用して、ネストされたナビゲーター2ナビゲーションプロップを子に渡します。

export default class Home extends Component {
    static navigationOptions = {
        header:null
    };

    constructor(props) {
        super(props);
        this.state = {
            profileData: this.props.navigation.state.params,
            route_index: '',
        }
    }

    render() {
        return (
            <ParentNavigator screenProps={this.props.navigation} />
        );
    }
}

export const ParentNavigator = StackNavigator({
  // ScreenName : { screen : importedClassname }
  Nested1: { screen: nested1 },
  Nested2: { screen : nestes1 }
});

export const nested1 = StackNavigator({
  ScreenA: { screen: screenA },
  ScreenB: { screen : screenB }
});

export const nested2 = StackNavigator({
  ScreenC: { screen: screenC },
  ScreenD: { screen : screenD }
});

を使用して、子供のナビゲーションを受け取ることができます

const {navigate} = this.props.screenProps.navigation;

これで、このnavigate()を使用して子間をナビゲートできます。

私はこのプロセスが少し混乱することを受け入れますが、私は解決策を見つけることができなかったので、私の要件を完了する必要があるので、これを使わなければなりませんでした。

0
HungrySoul