Skip to content

Instantly share code, notes, and snippets.

@karol-majewski
Last active May 24, 2021 23:14
Show Gist options
  • Save karol-majewski/b42dece0066576318088c2ea5362bc26 to your computer and use it in GitHub Desktop.
Save karol-majewski/b42dece0066576318088c2ea5362bc26 to your computer and use it in GitHub Desktop.
Memoize a function based on a custom equality function (+ use case for unique symbol)
type AnyFunction = (...args: any[]) => any;
/**
* Creates a memoized function that preserves reference equality based on a predicate function.
*
* @param fn Function which return value will be memoized.
* @param isEqual Should return `true` when two objects are considered identical.
*
* @example
*
* ```ts
* const fn = memoize(() => ({ foo: 1, nonce: 2 }), (previous, next) => previous.foo === next.foo);
*
* const first = fn();
* const second = fn();
*
* first === second; // true
* ```
*/
export function memoize<T extends AnyFunction>(
fn: T,
isEqual: (previous: ReturnType<T>, next: ReturnType<T>) => boolean = Object.is
): (...params: Parameters<T>) => ReturnType<T> {
const nothing: unique symbol = Symbol();
let previous: ReturnType<T> | typeof nothing = nothing;
return (...params: Parameters<T>) => {
const current = fn(params);
if (previous === nothing || !isEqual(previous, current)) {
previous = current;
return current;
}
return previous;
};
}
@karol-majewski
Copy link
Author

karol-majewski commented Feb 26, 2021

Use to memoize the value of the state variable used in React.Context:

getMemoizedValue = memoize(() => this.state.value, (previousState, nextState) => previousState.foo === nextState.foo)

render() {
	return (
        <Context.Provider value={this.getMemoizedValue()}>{this.props.children}</Context.Provider>
    )
}

shouldComponentUpdate can also be used.

For function components, use this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment