Blazing fast memoization library for JavaScript with comprehensive configuration options and React support
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Specialized memoization methods optimized for specific use cases including promises, React components, and argument serialization.
Specialized memoization for async functions and promises with automatic resolution caching.
/**
* Promise/async function memoization with automatic resolution caching
* Sets isPromise: true and updateExpire: true by default
* @returns Moizer optimized for promise-based functions
*/
promise: Moizer<{ isPromise: true }>;Usage Examples:
import moize from "moize";
// API call memoization
const fetchUser = async (userId: string) => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) throw new Error(`Failed to fetch user ${userId}`);
return response.json();
};
const memoizedFetchUser = moize.promise(fetchUser);
// First call - makes HTTP request
const user1 = await memoizedFetchUser("123");
// Second call - returns cached promise result
const user2 = await memoizedFetchUser("123");
// Database query memoization
const getUserFromDB = async (id: number) => {
const result = await db.query('SELECT * FROM users WHERE id = ?', [id]);
return result[0];
};
const memoizedDBQuery = moize.promise.maxAge(30000)(getUserFromDB);
// Combining with other options
const advancedPromiseMemoization = moize.promise
.maxSize(50)
.maxAge(60000)
.profile('api-calls')(fetchUser);Specialized memoization for React components with props-based caching.
/**
* React component memoization based on props comparison
* Creates component wrapper that memoizes based on props and context
* @returns Moizer optimized for React components
*/
react: Moizer<{ isReact: true }>;Usage Examples:
import moize from "moize";
import React from "react";
// Basic component memoization
interface UserCardProps {
user: {
id: number;
name: string;
email: string;
};
theme: 'light' | 'dark';
}
const UserCard: React.FC<UserCardProps> = ({ user, theme }) => (
<div className={`user-card user-card--${theme}`}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
const MemoizedUserCard = moize.react(UserCard);
// Component with deep props comparison
const ComplexComponent: React.FC<{
data: { items: any[]; metadata: Record<string, any> };
config: { showDetails: boolean; sortBy: string };
}> = ({ data, config }) => {
// Complex rendering logic
return <div>{/* rendered content */}</div>;
};
const MemoizedComplexComponent = moize.react.deep(ComplexComponent);
// With additional configuration
const OptimizedComponent = moize.react
.maxSize(10) // Keep 10 different prop combinations
.shallow // Use shallow comparison for props
(UserCard);
// Functional component with hooks
const CounterComponent: React.FC<{ initialCount: number }> = ({ initialCount }) => {
const [count, setCount] = React.useState(initialCount);
return (
<div>
<span>Count: {count}</span>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
</div>
);
};
const MemoizedCounter = moize.react(CounterComponent);Custom React hook pattern for using moize within functional components with hooks.
/**
* Custom hook pattern for memoization within React functional components
* Not a built-in export - user-implemented pattern from the documentation
*/
function useMoize<T extends (...args: any[]) => any>(
fn: T,
args: Parameters<T>,
options?: Options<T>
): ReturnType<T>;Implementation Example:
import { useRef } from 'react';
import moize from 'moize';
export function useMoize(fn, args, options) {
const moizedFnRef = useRef(moize(fn, options));
return moizedFnRef.current(...args);
}Usage Examples:
import React from 'react';
import { useMoize } from './moize-hooks';
function MyComponent({ first, second, object }) {
// Standard usage
const sum = useMoize((a, b) => a + b, [first, second]);
// With options
const deepSum = useMoize((obj) => obj.a + obj.b, [object], {
isDeepEqual: true,
});
return (
<div>
Sum of {first} and {second} is {sum}. Sum of {object.a} and{' '}
{object.b} is {deepSum}.
</div>
);
}
// Advanced usage with complex computations
function DataProcessingComponent({ data, filters, sortBy }) {
// Expensive data processing with memoization
const processedData = useMoize(
(items, filterConfig, sort) => {
return items
.filter(item => filterConfig.active ? item.status === 'active' : true)
.filter(item => filterConfig.category ? item.category === filterConfig.category : true)
.sort((a, b) => sort === 'name' ? a.name.localeCompare(b.name) : a.id - b.id);
},
[data, filters, sortBy],
{
isDeepEqual: true,
maxSize: 10,
profileName: 'data-processing'
}
);
// Complex calculation with custom equality
const aggregatedStats = useMoize(
(items) => ({
total: items.length,
active: items.filter(item => item.status === 'active').length,
categories: [...new Set(items.map(item => item.category))].length,
avgValue: items.reduce((sum, item) => sum + item.value, 0) / items.length
}),
[processedData],
{
maxAge: 30000, // 30 second TTL
isShallowEqual: true
}
);
return (
<div>
<h3>Processed Data ({processedData.length} items)</h3>
<div>Stats: {aggregatedStats.active} active, {aggregatedStats.categories} categories</div>
{/* Render processed data */}
</div>
);
}Memoization using argument serialization for complex cache key generation.
/**
* Serialization-based memoization using default JSON serialization
* Converts arguments to strings for cache key comparison
* @returns Moizer with serialization enabled
*/
serialize: Moizer<{ isSerialized: true }>;
/**
* Serialization-based memoization with custom serializer
* @param serializer Custom function to serialize cache keys
* @returns Moizer with custom serialization
*/
serializeWith<Serializer extends Serialize>(
serializer: Serializer
): Moizer<{ isSerialized: true; serializer: Serializer }>;
type Serialize = (key: Key) => string[];
type Key<Arg extends any = any> = Arg[];Usage Examples:
import moize from "moize";
// Default JSON serialization
const processComplexObject = (obj: {
data: any[];
options: Record<string, any>;
}) => {
return obj.data.map(item => ({ ...item, ...obj.options }));
};
const serializedMemoized = moize.serialize(processComplexObject);
const obj1 = { data: [{ id: 1 }], options: { active: true } };
const obj2 = { data: [{ id: 1 }], options: { active: true } }; // Different objects, same content
console.log(serializedMemoized(obj1)); // Computed
console.log(serializedMemoized(obj2)); // Cached (serialization matches)
// Custom serialization
const customSerializer = (key: any[]) => {
return key.map(arg => {
if (typeof arg === 'object' && arg !== null) {
// Sort object keys before stringifying for consistent serialization
const sortedObj = Object.keys(arg)
.sort()
.reduce((result, key) => {
result[key] = arg[key];
return result;
}, {} as any);
return JSON.stringify(sortedObj);
}
return String(arg);
});
};
const customSerializedMemoized = moize.serializeWith(customSerializer)(processComplexObject);
// Serialization with other options
const advancedSerialized = moize.serialize
.maxSize(20)
.maxAge(45000)
.profile('serialized-operations')(processComplexObject);
// Case-insensitive string serialization
const caseInsensitiveSerializer = (key: any[]) => {
return key.map(arg => {
if (typeof arg === 'string') {
return arg.toLowerCase();
}
return typeof arg === 'object' ? JSON.stringify(arg) : String(arg);
});
};
const textProcessor = (text: string, options: { trim: boolean }) => {
return options.trim ? text.trim().toUpperCase() : text.toUpperCase();
};
const caseInsensitiveMemoized = moize.serializeWith(caseInsensitiveSerializer)(textProcessor);
console.log(caseInsensitiveMemoized("Hello", { trim: true })); // Computed
console.log(caseInsensitiveMemoized("HELLO", { trim: true })); // Cached (case-insensitive)Specialized methods can be combined with other moize features for comprehensive optimization.
import moize from "moize";
// Promise memoization with size and TTL limits
const apiCall = async (endpoint: string, params: Record<string, any>) => {
const url = new URL(endpoint);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.append(key, String(value));
});
const response = await fetch(url.toString());
return response.json();
};
const optimizedApiCall = moize.promise
.serialize // Handle complex params objects
.maxSize(100) // Cache up to 100 different calls
.maxAge(300000) // 5 minute TTL
.profile('api') // Monitor performance
(apiCall);
// React component with deep comparison and size limit
const DataVisualization: React.FC<{
data: Array<{ id: string; values: number[] }>;
config: {
chartType: 'bar' | 'line' | 'pie';
colors: string[];
showLegend: boolean;
};
}> = ({ data, config }) => {
// Complex chart rendering
return <div>{/* chart content */}</div>;
};
const MemoizedVisualization = moize.react
.deep // Deep comparison for data and config
.maxSize(5) // Keep 5 different data/config combinations
(DataVisualization);Different specialized methods have different performance characteristics: