1

Similar to Access React Context outside of render function but I am looking to add a way of extending Alert.alert so that it will use the color scheme from theme.

  const { colorScheme } = useTheming();
...
    Alert.alert(t`logout`, "Are you sure you want to logout?", [
      {
        text: "No",
      },
      {
        style: "destructive",
        text: "Yes",
        onPress: logoutAsync,
      },
    ], {
      userInterfaceStyle: colorScheme
    });

I just want it so that the color scheme does not need to be added in.

I started with

import { Alert as RNAlert } from 'react-native'
export class Alert implements RNAlert {
  static alert(...) {
     // how do I get the data from the context?
  }
  static prompt(...) {
  }
}
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
  • `userInterfaceStyle` is an iOS only thing, so if you want to same alert functionality on both iOS and android, then you will want to make your own Alert component (which will be an absolutely position modal). While more work, it will give you total control over how customizable the modal/alert can be – PhantomSpooks Dec 30 '22 at 09:22
  • Also is it absolutely necessary for you to use a class component? – PhantomSpooks Dec 30 '22 at 10:06
  • I started to work out a custom alert demo but I was using hooks instead of class components https://snack.expo.dev/P6Smzk4FS – PhantomSpooks Dec 30 '22 at 10:08
  • If the alert prop accepted a buttons array where each item was a button title and an onPress function you could easily add buttons to the modal and get it to look really similar to the alert api – PhantomSpooks Dec 30 '22 at 10:13
  • And if you used `onLayout` to get the view y and height, that calls the alert, you use layout.y + layout.height to position the modal directly under the View – PhantomSpooks Dec 30 '22 at 10:17
  • The problem is to use it in a non-component scenario form like the `Alert.alert` API itself. `Alert` isn't a class component, it's just an API. I wanted to wrap a non-React component API to use hooks which I don't think is possible. – Archimedes Trajano Dec 30 '22 at 19:28

1 Answers1

0

This isn't a proper answer yet since I don't wrap the Alert object, but this is the closest I have gotten.

import { useCallback } from 'react';
import { Alert as RNAlert, AlertButton, AlertOptions } from 'react-native';
import { useTheming } from "./ThemeContext";

export function useAlert(): RNAlert {
    const { colorScheme } = useTheming();
    const alert = useCallback((title: string, message?: string, buttons?: AlertButton[], options?: AlertOptions): void => {
        const newOptions = { userInterfaceStyle: options?.userInterfaceStyle ?? colorScheme, ...options }
        RNAlert.alert(title, message, buttons, newOptions);
    }, [colorScheme])
    return { alert, prompt: RNAlert.prompt };
}

The key thing to watch out for is when you're using it with useCallback you have to remember to add the new alert to the dependency list.

  const { alert } = useAlert();
  ...
  const handleLogout = useCallback(() => {
    alert(t`logout`, "Are you sure you want to logout?", [
      {
        text: "No",
      },
      {
        text: "Yes",
        onPress: logoutAsync,
      },
    ]);
  }, [logoutAsync, alert]);
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265