React hooks
React Hooks are powerful functions that enable state management and lifecycle handling within functional components-capabilities that were previously limited to class components. With hooks like useState
for managing local state and useEffect
for handling side effects, developers can write cleaner, more modular code. Hooks promote reusability by allowing you to encapsulate stateful logic, while adhering to specific rules - such as calling hooks only at the top level and always prefixing them with use
- to maintain predictable and consistent behavior.
Below is a curated collection of useful React Hooks developed specifically for use across various Kommo projects, integrations, and widgets.
Installation
Installations options are available in the public GitHub repository.
npm | yarn | pnpm |
---|---|---|
npm i @kommo-crm/react-hooks | yarn add @kommo-crm/react-hooks | pnpm add @kommo-crm/react-hooks |
Hooks
useConst
useConst
This hook is designed to be used instead of
useMemo
with an empty array of dependencies
React hook that memoize the value returned by the fn
function each time the Component
is called. It ensures that the value is saved between renderings of the component to avoid recalculating and recreating the value each time the component is updated.
Usage
import React from 'react';
import { useConst } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const value = useConst<number>(() => {
console.log("Calculating expensive value...");
return Math.random();
});
return (
<div>
<p>Value: {value}</p>
</div>
);
};
Reference
const value = useConst(fn: () =>);
value
- immutable value obtained from a function callfn: () =>
- callback that will be called and return value
useDebounce
useDebounce
React hook that delays state changes until after wait milliseconds have elapsed since the last time the debounced function was invoked. The debounce delay will start when one of the values changes.
Usage
import React, { useState, ChangeEvent } from 'react';
import { useDebounce } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const [searchTerm, setSearchTerm] = useState("");
const debouncedSearchTerm = useDebounce(searchTerm, 500);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setSearchTerm(e.target.value);
};
return (
<div>
<h1>Debounced Search</h1>
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={handleChange}
/>
<p>Searching for: {debouncedSearchTerm}</p>
</div>
);
};
Reference
const debouncedValue = useDebounce(value: T, delay: number);
debouncedValue
- current delayed valuevalue: T
- value, the change of which triggers the delaydelay: number
- delay in milliseconds
useDidUpdateEffect
useDidUpdateEffect
React hook which allows you to execute an effect only after the first render and all the next renders. This hook emulates the behavior of componentDidUpdate
.
Usage
import React,{useState} from 'react';
import { useDidUpdateEffect } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const [count, setCount] = useState(0);
useDidUpdateEffect(() => {
console.log("Effect triggered after initial render");
}, [count]);
return (
<div>
<h1>useDidUpdateEffect Example</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
</div>
)
};
Reference
useDidUpdateEffect(fn: () =>, inputs?: React.DependencyList): void;
fn: () =>
- function that will be calledinputs: DependencyList
- array of values that the function call depends on, in the same manner asuseEffect
useKeyboardListNavigation
useKeyboardListNavigation
React hook that manages keyboard navigation for a list of items. It provides functionality to navigate up and down the list using arrow keys, select an item and toggle a state.
Usage
import React, { useState } from 'react';
import { useKeyboardListNavigation } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const items = ['Item 1', 'Item 2', 'Item 3'];
const [isOpen, setIsOpen] = useState(true);
const { currentHoveredIndex, onKeyDown, updateListPosition } = useKeyboardListNavigation({
itemsLength: items.length,
isOpened: isOpen,
hoveredIndex: 0,
onSelect: (index) => alert(`Selected: ${items[index]}`),
onToggle: () => setIsOpen((prev) => !prev),
});
return (
<div onKeyDown={onKeyDown} tabIndex={0}>
<h1>Keyboard Navigation</h1>
{isOpen && (
<ul>
{items.map((item, index) => (
<li
key={item}
style={{
background: index === currentHoveredIndex ? 'lightblue' : 'transparent',
}}
>
{item}
</li>
))}
</ul>
)}
</div>
);
};
Reference
const { currentHoveredIndex, onKeyDown, updateListPosition, } = useKeyboardListNavigation(
options: UseKeyboardListNavigationOptions);
currentHoveredIndex: number
- the index of the currently hovered item;onKeyDown: (event: React.KeyboardEvent) => void
- handler function for keyboard events;updateHoveredIndex: (index: number) => void
- Function for update hovered index;updateListPosition: (index: number) => void
- Function for update hovered index and list position;
useIsComponentMounted
useIsComponentMounted
This hook designed to be used to avoid state updates on unmounted components.
A React hook that returns a function to determine if the component is currently mounted.
Usage
import React from 'react';
import { useIsComponentMounted } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const isMounted = useIsComponentMounted();
useEffect(() => {
setTimeout(() => {
if (isMounted()) {
// ...
} else {
// ...
}
}, 1000);
}, []);
};
Reference
const isMounted = useIsComponentMounted(): (() => boolean);
isMounted: Function
- function that will return true if component mounted and false otherwise;
useOnOutsideClick
useOnOutsideClick
This hook is designed to track a click outside of the passed DOM element.
Custom hook that handles clicks outside a specified element.
Usage
import React, { useRef } from 'react';
import { useOnOutsideClick } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const ref = useRef<HTMLDivElement>(null);
useOnOutsideClick({
ref,
handler: (event) => {
console.log('Clicked outside the element', event);
},
});
return (
<div>
<div ref={ref} style={{ padding: '20px', background: '#f0f0f0' }}>
Click inside this box
</div>
<p>Click outside the box to trigger the handler.</p>
</div>
);
};
Reference
const useOnOutsideClick: ({
ref,
handler,
context,
}: UseOnOutsideClickOptions) => void;
ref: MutableRefObject<HTMLElement>
- ref DOM element, click outside of which will be tracked and processed handlerhandler: Function
- function that will be called when clicking outside the refcontext: string
- context for grouping handlers and tracked items. If specified, handlers and links will be grouped within the specified context. Handlers of one context will not affect handlers of other contexts.global
- General context used by default
useDeepCompareEffect
useDeepCompareEffect
React hook which allows you to execute an effect only when the dependencies deeply change. This hook is useful when you want to avoid unnecessary effect executions due to shallow comparison of dependencies.
Usage
import React, { useState } from 'react';
import { useDeepCompareEffect } from '@kommo-crm/react-hooks';
const Demo: React.FC = () => {
const [data, setData] = useState({ count: 0 });
useDeepCompareEffect(() => {
console.log("Effect triggered due to deep change in dependencies");
}, [data]);
useEffect(() => {
console.log("Effect triggered due to usual change in dependencies");
}, [data]);
return (
<div>
<h1>useDeepCompareEffect Example</h1>
<p>Count: {data.count}</p>
<button onClick={() => setData({ count: data.count + 1 })}>Increment Count</button>
<button onClick={() => setData({ count: data.count })}>New object without effect</button>
</div>
)
};
Links
Updated 3 days ago