Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use with Hooks #225

Open
blackwolf08 opened this issue Jun 11, 2020 · 11 comments
Open

Use with Hooks #225

blackwolf08 opened this issue Jun 11, 2020 · 11 comments

Comments

@blackwolf08
Copy link

blackwolf08 commented Jun 11, 2020

Short Description

Improves Documentation

Steps to Reproduce / Code Snippets / Usage

import React, { useRef } from "react";
import DropdownAlert from "react-native-dropdownalert";

const DropDownContext = React.createContext();

export const DropDownComponentProvider = ({ children }) => {
  let ref = useRef();
  return (
    <DropDownContext.Provider
      value={{
        ref,
      }}
    >
      {children}
      <DropdownAlert ref={ref} />
    </DropDownContext.Provider>
  );
};

export const useDropDown = () => React.useContext(DropDownContext);

In App.js

import React from "react";
import { AppearanceProvider } from "react-native-appearance";
import {
  AuthProvider,
  DropDownComponentProvider,
  ThemeProvider,
  UserProvider,
} from "./contexts";
import { firebaseInit } from "./firebase";
import NavigationConatiner from "./navigation";

// init firebase app
firebaseInit();

export default function App() {
  
  return (
    <DropDownComponentProvider>
      <UserProvider>
        <AuthProvider>
          <AppearanceProvider>
            <ThemeProvider>
              <NavigationConatiner />
            </ThemeProvider>
          </AppearanceProvider>
        </AuthProvider>
      </UserProvider>
    </DropDownComponentProvider>
  );
}

Then in any component

import { useDropDown } from "./location"

// Inside a functional component 

const { ref } = useDropDown()

// eg in use effect
   useEffect(() => {
    ref.current.alertWithType("success", "Log in successfull.", "asdasd");
  }, []);
@blackwolf08
Copy link
Author

I hope it helps :)

@Lazymondaysunday
Copy link

This seems to work, any idea how you would pass functions for onTap, onClose.

@blackwolf08
Copy link
Author

@Lazymondaysunday pass it in context, where i am passing the ref

@Lazymondaysunday
Copy link

@Lazymondaysunday pass it in context, where i am passing the ref

I'm trying to do it, but can't figure it out. Could you paste an example? Thanks!

@pors
Copy link

pors commented Jan 21, 2021

@Lazymondaysunday pass it in context, where i am passing the ref

I'm trying to do it, but can't figure it out. Could you paste an example? Thanks!

@blackwolf08 I'm also not sure how to do this. E.g. how do we set the closeInterval in the component where ref.current.alertWithType is called?

@christhoval06
Copy link

useDropdownAlert.js

/**
 * @author: Christhoval Barba <christhoval@gmail.com>
 * @flow
 * @format
 */
import React, {createContext, useRef, useMemo, useState, useContext} from 'react';
import {DropdownAlert} from 'components/dropdownAlert';
import type {DropdownAlertType} from 'react-native-dropdownalert';

export type AlertWithTypeFn = (
  type: DropdownAlertType,
  title: string,
  message: string,
  payload?: {[string]: string},
  interval?: number,
) => void;

export type AlertContextType = {
  alertWithType: AlertWithTypeFn,
};

const AlertContext: React$Context<AlertContextType> = createContext<AlertContextType>({
  alertWithType() {},
});
const {Provider, Consumer} = AlertContext;

type React$Reference<T> = {current: React$ElementRef<T> | null};

export function DropdownAlertProvider({children}: {children: React$Node}): React$Element<typeof Provider> {
  const [alertType, setAlertType] = useState<string>('');
  const dropdown: React$Reference<DropdownAlertType> = useRef();
  const contextValue: AlertContextType = useMemo(
    () => ({
      alertWithType: (
        type: DropdownAlertType,
        title: string,
        message: string,
        payload?: {[string]: string},
        interval?: number,
      ) => {
        setAlertType(type);
        dropdown?.current?.alertWithType(type, title, message, payload, interval);
      },
    }),
    [dropdown],
  );
  return (
    <Provider value={contextValue}>
      {React.Children.only(children)}
      <DropdownAlert ref={dropdown} alertType={alertType} />
    </Provider>
  );
}

export function withAlert<T>(
  Component: React$ComponentType<AlertContextType & T>,
): React$StatelessFunctionalComponent<T> {
  return function WrapperComponent(props: T): React$Element<typeof Consumer> {
    return <Consumer>{(value: AlertContextType) => <Component {...props} {...value} />}</Consumer>;
  };
}

export const useDropdownAlert = (): AlertContextType => {
  const context = useContext<AlertContextType>(AlertContext);

  if (context === undefined) {
    throw new Error('useDropdownAlert was used outside of its Provider -> DropdownAlertProvider');
  }

  return context;
};

export default DropdownAlertProvider;

in App.js

...
return (
  <DropdownAlertProvider>
       ...
  </DropdownAlertProvider>
);
...

in Component

...
const Component = ({props}: Props) => {
    const {alertWithType} = useDropdownAlert();
    
    const showDropdown = useCallback(() => {
         ...
         alertWithType('error', 'title', 'message');
         ...
     }, [alertWithType]);

    ...
}

@pors
Copy link

pors commented Apr 16, 2022

@christhoval06 awesome, thanks a lot!

Do you maybe have a solution for the "alert behind modal" problem as well?
It is a bit of a hassle to not use the provider for all modals.

@christhoval06
Copy link

@pors current solution wrap Modal with AlertProvider and use hook.

Modals use different index or elevation, then alerts and other modal is behind

@rajscet
Copy link

rajscet commented Aug 4, 2022

Short Description

Improves Documentation

Steps to Reproduce / Code Snippets / Usage

import React, { useRef } from "react";
import DropdownAlert from "react-native-dropdownalert";

const DropDownContext = React.createContext();

export const DropDownComponentProvider = ({ children }) => {
  let ref = useRef();
  return (
    <DropDownContext.Provider
      value={{
        ref,
      }}
    >
      {children}
      <DropdownAlert ref={ref} />
    </DropDownContext.Provider>
  );
};

export const useDropDown = () => React.useContext(DropDownContext);

In App.js

import React from "react";
import { AppearanceProvider } from "react-native-appearance";
import {
  AuthProvider,
  DropDownComponentProvider,
  ThemeProvider,
  UserProvider,
} from "./contexts";
import { firebaseInit } from "./firebase";
import NavigationConatiner from "./navigation";

// init firebase app
firebaseInit();

export default function App() {
  
  return (
    <DropDownComponentProvider>
      <UserProvider>
        <AuthProvider>
          <AppearanceProvider>
            <ThemeProvider>
              <NavigationConatiner />
            </ThemeProvider>
          </AppearanceProvider>
        </AuthProvider>
      </UserProvider>
    </DropDownComponentProvider>
  );
}

Then in any component

import { useDropDown } from "./location"

// Inside a functional component 

const { ref } = useDropDown()

// eg in use effect
   useEffect(() => {
    ref.current.alertWithType("success", "Log in successfull.", "asdasd");
  }, []);

wow working great

@vishaldhanotiyadev
Copy link

vishaldhanotiyadev commented Aug 9, 2022

This solution worked but it failed when I try to execute the Test case with jest.

How I Used

  const {alertRef} = useDropDownAlert();
  alertRef?.current?.alertWithType('info', 'Info', text);

● InfoIcon component › InfoIcon render with onClick

TypeError: Cannot read properties of undefined (reading 'alertRef')

  22 |   const icon = props.iconName || Icons.INFO_CIRCLE;
  23 |
> 24 |   const {alertRef} = useDropDownAlert();
     |          ^
  25 |

@christhoval06
Copy link

@vishaldhanotiyadev you need provide a context provider to success test running.

Example

<DropdownAlertProvider>
... test
</DropdownAlertProvider >

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

7 participants