React useMemo和redux createSelector的区别
目录
一、createSelector
二、useMemo
三、主要区别
四、使用建议
使用 createSelector 的情况:
使用 useMemo 的情况:
五、组合使用
六、总结
七、createSelector使用案例
createSelector 和 useMemo 都是用于性能优化的记忆化(memoization)工具,但它们在用途、使用场景和实现机制上有重要区别:
一、createSelector
(Redux Toolkit/Reselect)
官网文档:https://redux.js.org/usage/deriving-data-selectors#createselector-overview
主要用于 Redux store state 的派生数据计算:
import { createSelector } from '@reduxjs/toolkit'const selectUsers = state => state.users
const selectFilters = state => state.filters// 创建记忆化的selector
export const selectFilteredUsers = createSelector([selectUsers, selectFilters],(users, filters) => {// 只有当 users 或 filters 改变时才重新计算return users.filter(user => user.name.includes(filters.search) && user.active === filters.activeOnly)}
)// 在组件中使用
const filteredUsers = useSelector(selectFilteredUsers)
二、useMemo
(React Hook)
主要用于 组件内部 的昂贵计算:
import { useMemo } from 'react'function UserList({ users, filters }) {const filteredUsers = useMemo(() => {// 只有当 users 或 filters 改变时才重新计算return users.filter(user => user.name.includes(filters.search) && user.active === filters.activeOnly)}, [users, filters])return <div>{/* 渲染 filteredUsers */}</div>
}
三、主要区别
| 特性 | createSelector | useMemo |
|---|---|---|
| 使用场景 | Redux state 派生数据 | 组件内部计算 |
| 依赖来源 | Redux store state | 组件 props/state |
| 记忆化范围 | 全局(整个应用) | 组件实例级别 |
| 重新计算时机 | 输入selector结果变化时 | 依赖数组变化时 |
| 缓存策略 | 默认浅比较,可自定义 | 引用比较(Object.is) |
| 测试 | 易于单独测试 | 需要组件测试 |
四、使用建议
使用 createSelector 的情况:
-
从 Redux store 派生复杂数据
-
多个组件需要相同的派生数据
-
数据转换逻辑复杂或计算昂贵
// 推荐:复杂的Redux数据转换
export const selectUserStats = createSelector([selectUsers],(users) => ({total: users.length,active: users.filter(u => u.active).length,inactive: users.filter(u => !u.active).length})
)
使用 useMemo 的情况:
-
组件内部的昂贵计算
-
基于 props 或本地 state 的派生数据
-
优化子组件重渲染
// 推荐:组件内部计算
function Chart({ data, config }) {const processedData = useMemo(() => {return data.map(item => ({...item,value: item.value * config.multiplier}))}, [data, config])return <LineChart data={processedData} />
}
五、组合使用
两者可以结合使用以获得最佳性能:
// Redux selector - 第一层记忆化
export const selectProcessedData = createSelector([selectRawData],(rawData) => rawData.map(processRawData)
)// 组件内 - 第二层记忆化
function DataVisualization() {const processedData = useSelector(selectProcessedData)const [sortOrder, setSortOrder] = useState('asc')const sortedData = useMemo(() => {return [...processedData].sort((a, b) => sortOrder === 'asc' ? a.value - b.value : b.value - a.value)}, [processedData, sortOrder])return <DataTable data={sortedData} />
}
六、总结
createSelector 用于 Redux 状态管理的记忆化,而 useMemo 用于 React 组件内部的记忆化。根据数据来源和使用场景选择合适的工具。
七、createSelector使用案例
import { createSelector } from 'reselect'`输入选择器:从状态中提取原始数据`
const selectUser = (state) => state.user 【state.user 是 Redux Store 中的一个 slice】
const selectPosts = (state) => state.posts 【state.posts 是 Redux Store 中的一个 slice】`Reselect 的 createSelector 会按顺序将 输入选择器的返回值,作为参数传递给转换函数。因此,转换函数中的user 对应 selectUser的返回值(即state.user)posts 对应 selectPosts的返回值(即state.posts)`
const selectUserData = createSelector([selectUser, selectPosts], `【输入选择器数组】`(user, posts) => ({ `【转换函数】`username: user.name,postCount: posts.length,})
)
组件中使用:
import { useSelector } from 'react-redux'
import { selectUserData } from './selectors'const Component = () => {const { username, postCount } = useSelector(selectUserData)return (<div><h3>{username}</h3><p>Posts: {postCount}</p></div>)
}
到此!
