1.Redux Toolkit 是什么?

358 阅读4分钟
  • Redux Toolkit是我们官方的,开箱即用的高效 Redux 开发工具集

  • package-lock.json 依赖包 image.png

  • 迭代版本 image.png

  • Redux 同步数据流 one-way-data-flow-04fe46332c1ccb3497ecb04b94e55b97.png

  • Redux异步数据流 ReduxAsyncDataFlowDiagram-d97ff38a0f4da0f327163170ccc13e80.gif

  • Redux 三大原则

    • 单一数据源,整个应用的 全局 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
    • State 是只读的,唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
    • 使用纯函数来执行修改,为了描述 action 如何改变 state tree,你需要编写纯的 reducers
  • Redux Toolkit解决的问题

    • 配置 Redux store 过于复杂
    • 我必须添加很多软件包才能开始使用 Redux 做事情
    • Redux 有太多样板代码
  • 案例 image.png image.png

configureStore

  • Redux工具包有一个 configureStore() 函数,其中覆盖了 createStore() 的功能
  • configureStore() 函数 提供简化的配置选项。它可以自动组合切片 slice 的 reducer,添加你提供的任何 Redux 中间件,默认 情况下包含 redux-thunk,并启用Redux DevTools 扩展

createSlice

  • createSlice函数允许我们提供一个带有reducer函数的对象,并且它将根据我们列出的 reducer 的名称自动生成 action type 字符串和 action creator 函数

  • createSlice 返回一个分片对象,该对象包含生成的 reducer 函数作为一个名为 reducer 的字段,以及在一个名为 actions 的对象中生成的 action creator

    • reducers 一个包含case reducer函数的对象,它的key将被用来生成动作类型常量并在派发的时候可见
    • prepare 可以用来自定义payload的值的创建
    • extraReducers 允许createSlice去响应别的slice创建的动作类型,它们不会用来生成actions

createAsyncThunk

  • 接收redux动作类型字符串和一个返回promise回调的函数
  • 它会基于你传递的动作类型前缀生成promise生命周期的动作类型
  • 并且返回一个thunk动作创建者,这个thunk动作创建者会运行promise回调并且派发生命周期动作
  • 它抽象了处理异步请求生命周期的标准推荐方法

createSelector / useSelector

思考: 有了 useSelector 还需要用 createSelector吗 ?

export const UserPage = ({ match }) => {
  const { userId } = match.params

  const user = useSelector(state => selectUserById(state, userId))

  const postsForUser = useSelector(state => {
    const allPosts = selectAllPosts(state)
    return allPosts.filter(post => post.user === userId)
  })
}

我们知道每发起一个 action 都将运行 useSelector,如果我们返回一个新的引用值,它会强制组件重新渲染。

我们在 useSelector 钩子中调用了 filter(),以便只返回属于该用户的帖子列表。不幸的是,这意味着 useSelector 总会 返回一个新的数组,所以 每次 执行以上操作我们的组件都将重新渲染,即使返回的数据并没有发生改变!

全等比较和更新 当函数组件渲染时,给定的 selector 函数将被调用,useSelector() hook 会返回其结果。(如果与前一次组件渲染对比,两次是相同的函数引用,hook 不会重新调用 selector,而是会返回缓存的结果)。

/** 默认是全等比较,在某些场合要用浅比较 */
import { useSelector, shallowEqual } from 'react-redux'
export function useShallowEqualSelector(selector) {
  return useSelector(selector, shallowEqual)
}

总结

  • React 的默认行为是当父组件渲染时,React 会递归渲染其中的所有子组件!

  • 可用于优化性能的记忆化 selector 函数

    • Redux Toolkit 重新导出了 Reselect 中的 createSelector 函数,该函数会生成记忆化的 selector
    • 只有当输入 selector 返回新的值时,记忆 selector 才会重新计算结果
    • 记忆化可以跳过昂贵的计算,并确保返回相同的结果引用
  • 可以使用多种方式来优化使用了 Redux 的 React 组件的渲染

    • 避免在 useSelector 中创建新的对象/数组引用——这将导致不必要的重新渲染
    • 可以传递记忆化的 selector 函数给useSelector来优化渲染
    • useSelector 可以接受比较函数,例如 shallowEqual,而不是引用相等
    • 组件可以包装在 React.memo() 中,仅在它们的 prop 发生变化时重新渲染
    • 列表渲染可以通过让列表父组件仅读取每项的 ID 组成的数组、将 ID 传递给列表项子项并在子项中按 ID 检索项来实现优化