Skip to content

useEffectCompare

Custom useEffect that reexecutes EffectCallback only when comparator function, received as third parameter, returns true.

Demo

INFO

The component has:

  • a state useState variable with id and name properties.
  • a messages useState variable with effect and effectCompare properties that are rendered.
  • a useEffect that update messages effect property when state change.
  • a useEffectCompare that update messages effect property. CompareFn returns true when state name property change.
  • a button with a function attached to onClick event that increment state id property.

Since compareFn compares only name property, useEffectCompare is reexecuted only once and its state value isn't updated. You can see this in dev tool console also.

Loading demo…
Show source code
tsx
import { useEffect, useState } from "react";
import { useEffectCompare } from "../../../..";

const UseEffectCompare = () => {
	const [state, setState] = useState({ id: 0, name: "state" });
	const [messages, setMessages] = useState({ effect: "", effectCompare: "" });

	useEffect(() => {
		console.log("useEffect execution..");
		setMessages(m => ({ ...m, effect: `useEffect --> Current state is: id: ${state.id} - name: ${state.name}` }));
		return () => {
			console.log("useEffect clean up execution..");
			setMessages(m => ({ ...m, effect: "" }));
		}
	}, [state]);

	useEffectCompare(
		() => {
			console.log("useEffectCompare execution..");
			setMessages(m => ({ ...m, effectCompare: `useEffectCompare --> Current state is: id: ${state.id} - name: ${state.name}` }));
			return () => {
				console.log("useEffectCompare clean up execution..");
				setMessages(m => ({ ...m, effectCompare: "" }));
			}
		},
		[state],
		(oldDeps, newDeps) => oldDeps[0].name !== newDeps[0].name
	);


	return (<>
		<p>Current state: id: {state.id} - name: {state.name}</p>
		<p>{messages.effect}</p>
		<p>{messages.effectCompare}</p>
		<button onClick={() => setState(t=> ({ ...t, id: t.id+1 }))}>Increment</button>
	</>);
};

UseEffectCompare.displayName = "UseEffectCompare";

export { UseEffectCompare };

Released under the MIT License.