1

react-navigation の defaultGetStateForAction を使用してナビゲーションをインターセプトしているため、保存されていないデータがあることをユーザーに警告し、ナビゲーションを続行して保存されていないデータを削除するか、最初に保存するかを選択できます。このデータは、screenProps を介して利用可能な関数によってアクセスできる、より高いコンポーネントの状態に格納されます。

だから...ここに私のコードがあります:

const CreateAnimalStack = createStackNavigator({
    CreateAnimal: { screen: createAnimalScreen },
    ListAnimals: { screen: listAnimalsScreen },
    DetailAnimal: { screen: detailAnimalScreen },
    ReviewAnimal: { screen: reviewAnimalScreen },
    ListMarks: { screen: listMarksScreen },
    CreateMark: { screen: createMarkScreen },
}, {
        initialRouteName: 'CreateAnimal',
    });

const defaultGetStateForAction = CreateAnimalStack.router.getStateForAction;

CreateAnimalStack.router.getStateForAction = (action, state) => {
    if (
        state &&
        action.type === NavigationActions.BACK &&
        state.routeName === 'CreateAnimal' &&
        state.routes[state.index].routeName === 'ReviewAnimal' &&
        state.index === 1
    ) {
        Alert.alert(
            'Alert Title',
            'My Alert Msg',
            [
                { text: 'Ask me later', onPress: () => console.log('Ask me later pressed') },
                {
                    text: 'Cancel',
                    onPress: () => {
                        return null;
                    },
                    style: 'cancel',
                },
                {
                    text: 'OK', onPress: () => {
                        const routes = [
                            { routeName: 'CreateAnimal' },
                        ];
                        return {
                            ...state,
                            routes,
                            index: 0,
                        };
                    }
                },
            ],
            { cancelable: false },
        );
        return state;

    } 
    return defaultGetStateForAction(action, state);
};

export default CreateAnimalStack;
4

1 に答える 1

0

Alertここでの主な問題は、ブロックされていないため、ナビゲーションがアラートの背後で引き続き発生することだと思います。

そうは言っても、react-navigation のドキュメントから、ステートメントnull内で返す必要があります: ナビゲーションがキャンセルされます。if

if (...) {
  Alert.alert(
      'Alert Title',
      'My Alert Msg',
      // ...
  );

  return null;
}

次に、Alert OK ボタンの解決で、(状態を返す代わりに) ナビゲーション アクションを再ディスパッチする必要がありますが、問題は、利用できないことdispatchです。dispatchから来ていAppContainerます。1 つの方法は、 doc で説明されているNavigationServiceように、ナビゲーターを格納するを作成し、 からエクスポートすることです。dispatch

// ...
{
    text: 'OK', onPress: () => {
        const action = NavigationActions.navigate({ routeName: 'CreateAnimal', params: {}});

        // here you have to call dispatch from the AppContainer navigator (NavigationService ?)
        NavigationService.dispatch(action);
    }
},

このコードはすべて壊れやすく、非常に醜いように思えます。

headerLeftたとえば、状態の変化をリッスンする代わりに、デフォルトのコンポーネントを screennavigationOptionsでカスタム onPress コールバックに置き換えるなど、まったく異なる方法を最初に検討することをお勧めします。

これは、react-navigation からデフォルトの左ボタンをインポートする単純でテストされていない例です。

import { HeaderBackButton } from 'react-navigation';

class YourScreen extends Component {
  static navigationOptions = ({ navigation }) => {
    const onBack = {
      Alert.alert(
        'Alert Title',
        'My Alert Msg',
        [
            { text: 'Ask me later', onPress: () => console.log('Ask me later pressed') },
            {
                text: 'Cancel',
                style: 'cancel',
            },
            {
                text: 'OK', onPress: () => {
                    navigation.goBack();
                }
            },
        ],
        { cancelable: false }
      );
    }

    return {
      headerLeft: <HeaderBackButton  onPress={() => onBack()} />
    }
}
于 2019-07-15T09:18:55.660 に答える