@craft-code/react-helper-utils v0.5.1
CraftCode React Helpers
this package containes the following:
- conetext:
helpers-context
- hooks:
useHelpersuseDebounceuseThrottleuseIntersectionObserveruseCRUDStateuseOutsideClickuseDialoguseMediaQuery
- components:
CollapsibleWrapperInfiniteListWrapperRenderIfHelpersContextProviderDialogContainer
- other:
helperFunctions
- zustand:
cookieStorage
helpers-context:
this context is used to pass any constant values to the functions / hooks / components that need them
it's required for some functions / hooks / components to work correctly
HOOKS:
1 - useHelpers
provides the usual collection of helper functions
that are used in most of our projects
and works as a wrapper for helperFunctions that pass the helpers-context value to it
| param | type |
|---|---|
| *none* | - |
⚠ must be used inside the
helpers-contextprovider to provide the necessary values to the functions
which includes:
fileExtensionToName,
filterFalseValuesFromAnObject,
// random
generateRandomId,
getRandomImageLink,
getImageServerLink,
matchIframeLink,
removeLineBreaksFromString,
// text manipulation
getFlagEmoji,
truncateString,
// html
sanitizeHtml,
// date-time
timeSpanToDate,
// youtube
getYoutubeLinkId,
getYoutubeLinkThumbnail,
generateYoutubeIFrameLink,
// whatsapp
goToWhatsappChat,
forwardMessageToWhatsApp,
// google
generateGoogleMapsUrlFromCords,
// friendly url
getIdFromFriendlyUrl,
generateFriendlyUrlFromId,
// local storage
getFromLocalStorage,
saveToLocalStorage,2 - useDebounce
| param | type |
|---|---|
| delayInMS* | number |
Usage:
const debounce1s = useDebounce(1000);
const debounce2s = useDebounce(2000);
if (isFulfiled) debounce1s(() => doSomething(...args)); // debounces for 1s
if (isFulfiled_2) debounce2s(() => doSomething(...args)); // debounces for 2s3 - useThrottle
| param | type |
|---|---|
| delayInMS* | number |
Usage:
const throttle1s = useThrottle(1000);
const throttle2s = useThrottle(2000);
if (isFulfiled) throttle1s(() => doSomething(...args)); // executes only once every 1s
if (isFulfiled_2) throttle2s(() => doSomething(...args)); // executes only once every 2s4 - useIntersectionObserver
returns the state of the observed element
| param | type |
|---|---|
| elementRef | Element | null |
| options | IntersectionObserverInit & {observeOnce: boolean;}; |
5 - useCRUDState
useState with operation flags and permissions control
| param | type |
|---|---|
| options | Partial<Params<T>> |
types
type Action = "ADD" | "EDIT" | "DELETE";
type Params<T> = {
initialData: T;
canAdd: boolean;
canEdit: boolean;
canDelete: boolean;
onActionDenied: (deniedAction: Action) => void;
emptyOnReset?: boolean;
};Usage:
interface Brand {
name: string;
logoSrc: string;
}
const { dispatch, is, state } = useCrudState<Partial<Brand>>({
canAdd,
canDelete,
canEdit,
});Note:
Setting
params.emptyOnResettotruewhen callingdispatch.RESET()will set state toundefinedwhile setting
params.emptyOnResettofalsewill set state toparams.initialData
6 - useOutsideClick
executes a function when clicking outside / inside of an element(s)
| param | type |
|---|---|
| elementRef* | MutableRefObject\<Element | null | undefined> | MutableRefObject\<Element | null | undefined>[] |
| outSideClickHandler | () => void |
| inSideClickHandler | (idx?: number) => void |
Usage:
const elementRef = useRef<any>();
const button1Ref = useRef<any>();
const button2Ref = useRef<any>();
const button3Ref = useRef<any>();
// single element
useOutsideClick(
elementRef,
() => alert("outside"),
() => alert("inside")
);
// multiple elements
useOutsideClick(
[button1Ref, button2Ref, button3Ref],
() => alert("outside all buttons"),
(idx) => alert(`inside button #${idx}`)
);7 - useDialog
enables the use of the new HTML <dialog/> element in a hook friendly form
must pass a ref to the <dialog/> element in the root of the app to the Helpers Context
Usage
App root:
import { DialogContainer, HelpersContextProvider } from '@craft-code/react-helper-utils'
const App => () => (
<HelpersContextProvider value={contextValue}>
...
...
<DialogContainer/> {/* <= this is where the content will be placed */}
<HelpersContextProvider/>
)your component:
import { useDialog } from '@craft-code/react-helper-utils'
const { open, close } = useDialog();
const SomeComponent = () => {
...
return <button onClick={() => open('content')}> Show Dialog </button>
}8 - useMediaQuery
creates a reactive value representing the matching of the provided media query
| param | type |
|---|---|
| query* | string (CSS media query string) |
| defaultValue | boolean |
8 - useDebounceState
creates a reactive state that returns a 3rd value that updates after a delay
AKA: mix of React's useState and useDebounce hook
| param | type |
|---|---|
| duration* | number |
| initialValue | T |
Usage
const [value, setValue, debouncedValue] = useDebounceState<string>(500, "");COMPONENTS:
1 - CollapsibleWrapper
Literally a simple div that collapse and expands vertically with absolutly no styling
| prop | type | description |
|---|---|---|
| isOpen* | boolean | controls the state of the containing div |
| fadeOpacity | boolean | fade the opacity of the content through the transition |
2 - InfiniteListWrapper
this component takes @tanstack/react-query infinite query
and takes care of fetching more data on reaching the end of the container
| prop | type | description |
|---|---|---|
| infiniteQueryResult* | UseInfiniteQueryResult\<T> | result of the infinite query hook |
| loadingComponent | ReactNode | component to show when loading more data |
| noDataComponent | ReactNode | component to show when there is no data |
| children | (Items: InfiniteData<T>[]) => ReactNode | control how to render the fetched data |
3 - RenderIf
this component only purpose is CODE READABILITY only, which is good enough 🙂, Really.
| prop | type | description |
|---|---|---|
| condition* | boolean | switch between main and fallback component |
| children | ReactNode | Main component to render conditionally |
| fallback | ReactNode | component to render when the condition is not meet |
Usage:
//before
{ condition ? (
/* main element code
.
.
. */
):( // the line that you keep searching for while coding
/* fallback element code
.
.
. */
)}// after
<RenderIf condition={condition} fallback={<fallbackComponent />}>
<MainComponent />
</RenderIf>4 - HelpersContextProvider
this component is the NEW RECOMMENDED WAY to use the helpers context
| prop | type | description |
|---|---|---|
| value* | IHelpersContextProvider | value to be passed to the components / hooks that need it |
| children | ReactNode |
5 - DialogContainer
this component is the container for the content passed to the useDialog hook
MUST be used inside
<HelpersContextProvider>& not<HelpersContext.Provider>otherwise it won't work
OTHER:
1 - helperFunctions
this is the backbone of the useHelpers hook that let you use them outside react components / hooks,
the hook is just a wrapper to access the HelpersContext value
ZUSTAND:
1 - cookieStorage
this is a custom storage to use in the zustand persist middleware that use cookies to save state
please note that cookie size limitations apply (max 4kB afaik).
usage
import { cookieStorage } from '@craft-code/react-helper-utils';
import { persist } from 'zustand/middleware';
const stateCreator = (set,get) => ({...})
const storage = create(persist(stateCreator,{name: 'storage', storage: () => cookieStorage}))there is a utility function to set expiry time on a cookie called setExpiry
| param | type |
|---|---|
| cookieName | string |
| date | Date | string |
usage:
import { setExpiry } from "@craft-code/react-helper-utils";
setExpiry("storage", "1997-08-21");Releases:
0.5.1
- bump up the version
0.5.0
InfiniteListWrapperupdated to support@tanstack/react-queryv5 changes- fixed some typos in the README file
0.4.3
- fixed export point
/native
0.4.2
- added export point for hooks that work with
react-native
0.4.1
- fixed a bug in
useCRUDStatewherestateandisvalues update in seperate renders
0.4.0
- removed
<HelpersContext.Provider/>component - replaced
useCreateCRUDStatehook withuseCRUDState - added
useDebounceState
0.3.6
<HelpersContext.Provider/> will be removed in future releases
please use <HelpersContextProvide/> instead
- added a custom
cookie storagestorage for zustandpersistmiddleware that is used to persist state in cookies - added
<HelpersContextProvider/>component as the new recommended way of using the context - added
useDialoghook to show dialogs using the new HTML<dialog/>element - added
<DialogContainer/>to show content provided touseDialog().openmethod - added
useMediaQueryto provide a reactive state that change according to media queries.matchesstate
0.3.5
- fixed
useDebouncenot triggering more than once some times
0.3.4
- removed extra debug info from render from
InfiniteListWrapper
0.3.3
- added useThrottle hook
0.3.2
- fixed noDataComponent & loadingComponent components showing up at the same time in
InfiniteListWrapper helperFunctionsdoesn't require default config
0.3.1
- add support for multiple elements to useOutsideClick hook
- useOutsideClick hook has
inSideClickHandlernow
0.3.0:
- 🔴 removed NextSEO
- added useOutsideClick hook
- added helperFunctions as a way to use the helper functions outside react components / hooks
0.2.0:
- configured code splitting
- added RenderIf component
0.1.0:
- initial release