Skip to content

Commit

Permalink
refactor: added handleOnUpdate to Portal
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhom committed Oct 17, 2021
1 parent c312e4c commit b000935
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

A simplified portal implementation for ⭕️ React Native ⭕️.

![React Native Bottom Sheet](./preview.jpg)
![React Native Portal](./preview.jpg)

---

Expand Down
2 changes: 1 addition & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const App = () => {
return (
<PortalProvider>
<ShowcaseApp
name="Bottom Sheet"
name="Portal"
description={description}
version={version}
author={author}
Expand Down
67 changes: 49 additions & 18 deletions src/components/portal/Portal.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,76 @@
import { memo, useEffect, useMemo } from 'react';
import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
import { nanoid } from 'nanoid/non-secure';
import { usePortal } from '../../hooks';
import type { PortalProps } from './types';

const PortalComponent = ({
name: _providedName,
hostName,
handleOnMount,
handleOnUnmount,
handleOnMount: _providedHandleOnMount,
handleOnUnmount: _providedHandleOnUnmount,
handleOnUpdate: _providedHandleOnUpdate,
children,
}: PortalProps) => {
//#region hooks
const { addPortal, removePortal, updatePortal } = usePortal(hostName);
const { addPortal: addUpdatePortal, removePortal } = usePortal(hostName);
//#endregion

//#region variables
const name = useMemo(() => _providedName || nanoid(), [_providedName]);
//#endregion

//#region effects
useEffect(() => {
if (handleOnMount) {
handleOnMount(() => addPortal(name, children));
//#region refs
const handleOnMountRef = useRef<typeof _providedHandleOnMount>();
const handleOnUnmountRef = useRef<typeof _providedHandleOnUnmount>();
const handleOnUpdateRef = useRef<typeof _providedHandleOnUpdate>();
//#endregion

//#region callbacks
const handleOnMount = useCallback(() => {
if (_providedHandleOnMount) {
_providedHandleOnMount(() => addUpdatePortal(name, children));
} else {
addPortal(name, children);
addUpdatePortal(name, children);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [_providedHandleOnMount, addUpdatePortal]);
handleOnMountRef.current = handleOnMount;

const handleOnUnmount = useCallback(() => {
if (_providedHandleOnUnmount) {
_providedHandleOnUnmount(() => removePortal(name));
} else {
removePortal(name);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [_providedHandleOnUnmount, removePortal]);
handleOnUnmountRef.current = handleOnUnmount;

const handleOnUpdate = useCallback(() => {
if (_providedHandleOnUpdate) {
_providedHandleOnUpdate(() => addUpdatePortal(name, children));
} else {
addUpdatePortal(name, children);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [_providedHandleOnUpdate, addUpdatePortal, children]);
handleOnUpdateRef.current = handleOnUpdate;
//#endregion

//#region effects
useEffect(() => {
handleOnMountRef.current?.();
return () => {
if (handleOnUnmount) {
handleOnUnmount(() => removePortal(name));
} else {
removePortal(name);
}
handleOnUnmountRef.current?.();

// remove callbacks refs
handleOnMountRef.current = undefined;
handleOnUnmountRef.current = undefined;
handleOnUpdateRef.current = undefined;
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
updatePortal(name, children);
// eslint-disable-next-line react-hooks/exhaustive-deps
handleOnUpdateRef.current?.();
}, [children]);
//#endregion

Expand Down
11 changes: 9 additions & 2 deletions src/components/portal/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ReactNode } from 'react';

export interface PortalProps {
/**
* Portal's key or name to be used as an identifer.
* Portal's key or name to be used as an identifier.
* @type string
* @default nanoid generated unique key.
*/
Expand All @@ -23,10 +23,17 @@ export interface PortalProps {
/**
* Override internal un-mounting functionality, this is useful
* if you want to trigger any action before un-mounting the portal content.
* @type (mount?: () => void) => void
* @type (unmount?: () => void) => void
* @default undefined
*/
handleOnUnmount?: (unmount?: () => void) => void;
/**
* Override internal updating functionality, this is useful
* if you want to trigger any action before updating the portal content.
* @type (update?: () => void) => void
* @default undefined
*/
handleOnUpdate?: (update?: () => void) => void;
/**
* Portal's content.
* @type ReactNode
Expand Down

0 comments on commit b000935

Please sign in to comment.