Open blackwolf08 opened 4 years ago
I hope it helps :)
This seems to work, any idea how you would pass functions for onTap, onClose.
@Lazymondaysunday pass it in context, where i am passing the ref
@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!
@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?
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]);
...
}
@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.
@pors current solution wrap Modal with AlertProvider and use hook.
Modals use different index or elevation, then alerts and other modal is behind
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
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 |
@vishaldhanotiyadev you need provide a context provider to success test running.
Example
<DropdownAlertProvider>
... test
</DropdownAlertProvider >
Short Description
Improves Documentation
Steps to Reproduce / Code Snippets / Usage
In App.js
Then in any component