React NativeReact Native PaperReact Navigation barStylematerial-bottom-tabstabBarVisible

material-bottom-tabsのTabを非表示する方法〜React navigation〜

flower-4898286_1920 React Native
スポンサーリンク

条件・関連リソース

React Navigation v5 + React Native Paper を使い React Native アプリを開発する時、createMaterialBottomTabNavigator で作成した Tab を非表示にするため、tabBarVisible: false オプションを使っても何故か効かなかったので調べてみたら以下の公式サイトでは material-bottom-tabs だけ tabBarVisible オプションが見当たらなかったし、ネットで検索しても古い情報しかなかったので自分のやり方で解決 ( 回避 ) してみました。

以下は公式サイト:

条件:

  • Redux ToolkitでReduxを楽に使う〜React-Native〜 の「方法 #4:RTK + Redux Hooks」 を利用し設定します。
  • Stack Screen の HeaderReact Native PaperAppbar を利用しています。
  • この記事の内容は material-bottom-tabs だけに該当します。

関連リソース:

  • @react-navigation/material-bottom-tabs 5.1.0
  • @react-navigation/native 5.0.8
  • @react-navigation/stack 5.1.0
  • @reduxjs/toolkit 1.2.5
  • react-native-paper 3.6.0
  • react-redux 7.2.0
  • redux 4.0.5
  • など。。

実現したいこと!

MaterialBottomTab ( Parent Navigator )
└─ HomeStack ( Child Navigator )
└─ Home Screen
└─ Details Screen  ◀︎このスクリーンを開くと Tab を非表示にしたい!

設定方法

  • Step 1
    解決方法を見つける

    この記事は Tab bar can now be hidden #20 のリンクから始まりました。

    ...
       if (!this._isVisible()) {
        	barStyle['display'] = 'none';
    ...

    barStyle display none 。。なるほど!

  • Step 2
    barStyle オブジェクトを設定します。

    const MaterialBottomTab = createMaterialBottomTabNavigator();で作成したファイルが対象です。

    以下の barStyle オブジェクトに isTabVisible 変数が false になると Tab を隠すように設定を追加します。( 変数名はすべて任意 )

    // 'none'ではないと、効きません!
    ...
      return (
        <MaterialBottomTab.Navigator
          initialRouteName={INITIAL_ROUTE_NAME}
          barStyle={{
            display: isTabVisible ? null : "none"
          }}
    ...
  • Step 3
    Tab の条件をコントロールする State 値を設定します。

    ここで Redux Store を利用します。( 詳細:方法 #4:RTK + Redux Hooks )

    useSlice で Reducer を作成します。

    • Tab の初期状態 ( isTabVisible ) を表示 ( true ) に。
    • アクションクリエーター:setTabVisibility
    • State 値:action.payload
    // MaterialBottomTabSlice.js
    
    import { createSlice } from "@reduxjs/toolkit";
    const MaterialBottomTabSlice = createSlice({
      name: "MaterialBottomTab Control",
      initialState: { isTabVisible: true },
      reducers: {
        setTabVisibility: (state, action) => {
          Object.assign(state, { isTabVisible: action.payload });
        }
      }
    });
    
    export const { setTabVisibility } = MaterialBottomTabSlice.actions;
    export default MaterialBottomTabSlice.reducer;
    

    MaterialBottomTabNavigator を設定します。

    Parent Navigator :

    useSelector を利用し State 値 isTabVisible を取得します。

    取得した State 値で以下のように条件分岐します。
    ▶︎ display: isTabVisible ? null : "none"

    // MaterialBottomTabs.js 抜粋
    
    import { useSelector } from "react-redux";
    
    const MaterialBottomTab = createMaterialBottomTabNavigator();
    
    export function MaterialBottomTabsScreen() {
      const isTabVisible = useSelector(state => state.tabs.isTabVisible);
    ..
      return (
        <MaterialBottomTab.Navigator
          initialRouteName={INITIAL_ROUTE_NAME}
          barStyle={{
            backgroundColor: theme.dark ? activeSurfaceColor : theme.colors.primary,
            display: isTabVisible ? null : "none"
          }}

  • Step 4
    Stack Screenを設定します。

    Child Screen :

    Tab を隠すスクリーンで State 値を設定します。

    Home Screen から Details Screen に遷移すると、

    useEffect を使い setTabVisibility アクションクリエーターをdispatch して Redux Store を更新します。dispatch(setTabVisibility(false));することで Tab が非表示に変わります。

    また、Details Screen から離れる場合は true に戻します。

    下記の例では Go to Home ボタンをタップすると Tab が表示されます。

    // Details.js 
    
    import { setTabVisibility } from "redux/reducers/MaterialBottomTabSlice";
    import { useDispatch } from "react-redux";
    ...
    
    function DetailsScreen({ navigation }) {
      const dispatch = useDispatch();
      React.useEffect(() => {
        dispatch(setTabVisibility(false));
      }, []);
      return (
        <JScrollView>
          <View style={{ alignItems: "center", justifyContent: "center" }}>
            <JText>Details Screen</JText>
            <Button
              onPress={() => {
                navigation.navigate("Home");
                dispatch(setTabVisibility(true));
              }}
              mode="outlined"
            >
              Go to Home
            </Button>

    画面左上の Back ボタンをタップする場合も設定します。

    <Appbar.BackAction/>dispatch(setTabVisibility(true)); を追加すれば OK です。

    import { Appbar, Avatar } from "react-native-paper";
    import { setTabVisibility } from "redux/reducers/MaterialBottomTabSlice";
    import { useDispatch } from "react-redux";
    
    const JAppbarHeader = ({ scene, previous, navigation }) => {
      const dispatch = useDispatch();
    ..
          {previous ? (
            <Appbar.BackAction
              onPress={() => {
                navigation.goBack();
                dispatch(setTabVisibility(true));
              }}
            />
    ...

    これで設定は完了です!

動作確認

Redux Store の設定は以下の通りです。

...
const rootReducer = combineReducers({
  tabs: MaterialBottomTabReducer
});
...

まとめ

React navigation で material-bottom-tabs に tabBarVisible が使えなくても以上のやり方でも臨機応変策としては有効かと思います。( Android / iOS )

また、Redux Store の設定方法の詳細は別の記事になっていますので、興味のある方はご参考ください。

スポンサーリンク

コメント

タイトルとURLをコピーしました