memo
Create a memoized function that caches function results to avoid repeated calculations.
Basic Usage
typescript
import { memo } from 'radash'
const expensiveCalculation = memo((n: number) => {
console.log('Computing...')
return n * n * n
})
console.log(expensiveCalculation(5)) // Computing... 125
console.log(expensiveCalculation(5)) // 125 (returned from cache)
console.log(expensiveCalculation(3)) // Computing... 27
console.log(expensiveCalculation(5)) // 125 (returned from cache)
Syntax
typescript
function memo<T extends (...args: any[]) => any>(
fn: T,
options?: {
maxSize?: number
ttl?: number
}
): T
Parameters
fn
(function): The function to memoizeoptions
(object, optional): Configuration optionsmaxSize
(number, optional): Maximum number of cache entriesttl
(number, optional): Time to live for cache entries (milliseconds)
Return Value
Returns a memoized function with the same signature but cached results.
Examples
Basic Memoization
typescript
import { memo } from 'radash'
const fibonacci = memo((n: number): number => {
console.log(`Computing fibonacci(${n})`)
if (n <= 1) return n
return fibonacci(n - 1) + fibonacci(n - 2)
})
console.log(fibonacci(10)) // Compute and cache
console.log(fibonacci(10)) // Return from cache
console.log(fibonacci(5)) // Return from cache
Complex Parameter Memoization
typescript
import { memo } from 'radash'
interface User {
id: number
name: string
age: number
}
const getUserStats = memo((users: User[], filter: string) => {
console.log('Computing user stats...')
const filtered = users.filter(user =>
user.name.toLowerCase().includes(filter.toLowerCase())
)
return {
count: filtered.length,
averageAge: filtered.reduce((sum, user) => sum + user.age, 0) / filtered.length,
names: filtered.map(user => user.name)
}
})
const users: User[] = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Charlie', age: 35 }
]
console.log(getUserStats(users, 'alice')) // Compute
console.log(getUserStats(users, 'alice')) // Return from cache
console.log(getUserStats(users, 'bob')) // Compute
Async Function Memoization
typescript
import { memo } from 'radash'
const fetchUserData = memo(async (userId: number) => {
console.log(`Fetching user ${userId}...`)
const response = await fetch(`/api/users/${userId}`)
return response.json()
})
// Use memoized async function
async function getUser(userId: number) {
const user = await fetchUserData(userId)
console.log('User:', user)
return user
}
// First call will make request
await getUser(1)
// Second call will return from cache
await getUser(1)
With Cache Size Limit
typescript
import { memo } from 'radash'
const expensiveFunction = memo((input: string) => {
console.log(`Computing for: ${input}`)
return input.split('').reverse().join('')
}, { maxSize: 3 })
console.log(expensiveFunction('hello')) // Compute
console.log(expensiveFunction('world')) // Compute
console.log(expensiveFunction('test')) // Compute
console.log(expensiveFunction('hello')) // Return from cache
console.log(expensiveFunction('new')) // Compute, will clear oldest cache
With Time to Live Cache
typescript
import { memo } from 'radash'
const getCurrentTime = memo(() => {
console.log('Getting current time...')
return new Date().toISOString()
}, { ttl: 5000 }) // 5 second cache
console.log(getCurrentTime()) // Compute
console.log(getCurrentTime()) // Return from cache
// After 5 seconds
setTimeout(() => {
console.log(getCurrentTime()) // Recompute
}, 6000)
Object Parameter Memoization
typescript
import { memo } from 'radash'
const processConfig = memo((config: Record<string, any>) => {
console.log('Processing config...')
return {
...config,
processed: true,
timestamp: Date.now()
}
})
const config1 = { theme: 'dark', language: 'en' }
const config2 = { theme: 'light', language: 'zh' }
console.log(processConfig(config1)) // Compute
console.log(processConfig(config1)) // Return from cache
console.log(processConfig(config2)) // Compute
Array Parameter Memoization
typescript
import { memo } from 'radash'
const calculateArrayStats = memo((numbers: number[]) => {
console.log('Calculating array stats...')
return {
sum: numbers.reduce((acc, num) => acc + num, 0),
average: numbers.reduce((acc, num) => acc + num, 0) / numbers.length,
min: Math.min(...numbers),
max: Math.max(...numbers)
}
})
const numbers1 = [1, 2, 3, 4, 5]
const numbers2 = [6, 7, 8, 9, 10]
console.log(calculateArrayStats(numbers1)) // Compute
console.log(calculateArrayStats(numbers1)) // Return from cache
console.log(calculateArrayStats(numbers2)) // Compute
Multi-Parameter Memoization
typescript
import { memo } from 'radash'
const complexCalculation = memo((a: number, b: number, operation: string) => {
console.log(`Computing ${a} ${operation} ${b}...`)
switch (operation) {
case 'add':
return a + b
case 'multiply':
return a * b
case 'divide':
return a / b
default:
return a - b
}
})
console.log(complexCalculation(5, 3, 'add')) // Compute
console.log(complexCalculation(5, 3, 'add')) // Return from cache
console.log(complexCalculation(5, 3, 'multiply')) // Compute
Recursive Function Memoization
typescript
import { memo } from 'radash'
const factorial = memo((n: number): number => {
console.log(`Computing factorial(${n})`)
if (n <= 1) return 1
return n * factorial(n - 1)
})
console.log(factorial(5)) // Compute
console.log(factorial(5)) // Return from cache
console.log(factorial(3)) // Return from cache (because factorial(3) was computed when calculating factorial(5))
Conditional Memoization
typescript
import { memo } from 'radash'
const conditionalMemo = memo((value: string, shouldCache: boolean) => {
console.log(`Processing: ${value}`)
return value.toUpperCase()
})
// Decide whether to use cache based on condition
console.log(conditionalMemo('hello', true)) // Compute and cache
console.log(conditionalMemo('hello', true)) // Return from cache
console.log(conditionalMemo('hello', false)) // Compute (different parameters)
Cache Cleanup
typescript
import { memo } from 'radash'
const cachedFunction = memo((input: string) => {
console.log(`Processing: ${input}`)
return input.length
}, { maxSize: 2 })
console.log(cachedFunction('hello')) // Compute
console.log(cachedFunction('world')) // Compute
console.log(cachedFunction('test')) // Compute, will clear 'hello' cache
console.log(cachedFunction('hello')) // Recompute
Performance Optimization Example
typescript
import { memo } from 'radash'
// Simulate expensive calculation
const expensiveOperation = memo((data: number[]) => {
console.log('Performing expensive operation...')
// Simulate time-consuming calculation
let result = 0
for (let i = 0; i < 1000000; i++) {
result += data.reduce((sum, num) => sum + num, 0)
}
return result
})
const data1 = [1, 2, 3, 4, 5]
const data2 = [6, 7, 8, 9, 10]
console.time('First call')
console.log(expensiveOperation(data1))
console.timeEnd('First call')
console.time('Cached call')
console.log(expensiveOperation(data1))
console.timeEnd('Cached call')
console.time('New data call')
console.log(expensiveOperation(data2))
console.timeEnd('New data call')
Error Handling
typescript
import { memo } from 'radash'
const riskyFunction = memo((input: string) => {
console.log(`Processing: ${input}`)
if (input === 'error') {
throw new Error('Simulated error')
}
return input.toUpperCase()
})
try {
console.log(riskyFunction('hello')) // Works normally
console.log(riskyFunction('hello')) // Return from cache
console.log(riskyFunction('error')) // Throws error
} catch (error) {
console.error('Error:', error.message)
}
Notes
- Memory usage: Cache consumes memory, set appropriate maxSize
- Parameter comparison: Uses strict equality for parameter comparison
- Async functions: Supports async functions, but caches Promises
- Side effects: Avoid side effects in memoized functions
- Cache invalidation: Use ttl to set cache expiration time
Differences from Other Methods
memo()
: Memoization tool provided by radash- Manual caching: Requires implementing cache logic yourself
useMemo()
: React Hook, only for use within components
Practical Application Scenarios
- Mathematical calculations: Cache expensive mathematical operations
- API calls: Cache API responses
- Data processing: Cache data processing results
- Recursive functions: Optimize recursive algorithm performance
- Configuration processing: Cache configuration calculation results