0
点赞
收藏
分享

微信扫一扫

Dhtmlx Event Calendar 付费版使用

柠檬果然酸 2023-11-12 阅读 48

文章目录

异步逻辑

createAsyncThunk(一)

createAsyncThunk(二)

性能优化

createSelector


异步逻辑

//Product.js
const onAdd = () => {
       const name = nameRef.current.value
       // 触发添加商品的事件
       dispatch(addProduct({name}))
}

如果要让异步逻辑与Store交互,我们需要使用redux middleware。
Redux 有多种异步 middleware,每一种都允许你使用不同的语法编写逻辑。最常见的异步 middleware 是 redux-thunk ,它可以让你编写可能直接包含异步逻辑的普通函数。
Redux Toolkit 的 configureStore 功能默认自动设置 thunk middleware,我们推荐使用 thunk 作为 Redux 开发异步逻辑的标准方式。


Thunk 函数
在Thunk函数中我们可以编写异步逻辑的代码(例如 setTimeout 、Promise 和 async/await ),并且可以通过参数获取到dispatch,getState()。从而在异步操作执行后再diapacth action。
 

//slices/productSlice.js
import { createSlice } from '@reduxjs/toolkit'
//定义初始state
//list表示商品列表,isLoading表示是否为正在请求数据的状态
const initialState = { list: [] ,isLoading:false}
//创建slice
const slice = createSlice({
   //定义域名称
   name: 'product',
   //传入初始state
   initialState,
   //定义reducers
   reducers: {
       //这个reducer用来把商品数据存储到store中
       addProduct: (state, action) => {
state.list.push(action.payload)
      },
       //这个reducer用来更改isLoading
       changeState:(state,action)=>{
           state.isLoading=action.payload
      }
  }
})
//导出action creator
export const { addProduct ,changeState} = slice.actions
//导出thunk函数
//addProductAsync为thunk函数的创建函数,它返回一个thunk函数
//返回的thunk函数中我们就可以编写异步代码了
export const addProductAsync = (payload) => (dispatch, getState) => {
   //触发action ,改变isLoading的状态
   dispatch(changeState(true))
   setTimeout(() => {
       dispatch(addProduct(payload))
       //触发action ,改变isLoading的状态
       dispatch(changeState(false))
  }, 3000)
}

//导出reducer
export default slice.reducer
//pages/Product.js
import React, { useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux'
import { addProductAsync } from '../slices/productSlice'
//引入thunk函数
export default function Product() {
   const nameRef = useRef()
   const {list:productList,isLoading} = useSelector(state => state.product)
   const dispatch = useDispatch()
   const onAdd = () => {
       //thunk函数的使用,跟普通的action creator的使用一样
   
       dispatch(addProductAsync({ name: nameRef.current.value }))
  }
   return (
       <div>
          我是商品页面<br />
          商品名:<input ref={nameRef} required /><br />
          {isLoading?<div>请求数据中... </div>:productList.map((item, index) => <li key={index}>
              商品名:{item.name}
           </li>)}
           
           <button onClick={onAdd}>新增商品</button>
       </div>
  );
}

createAsyncThunk(一)

 Redux Toolkit 的 createAsyncThunk API 生成 thunk,为你自动 dispatch 那些 "状态" action。

 createAsyncThunk 接收 2 个参数:
1、 参数一:将用作生成的 action type的前缀的字符串
2 、一个 “payload creator” 回调函数,它应该返回一个 Promise 或者其他数据

 //slices/productSlice.js
//使用createAsyncThunk创建thunk
//接收的第一个参数是action 的 type的前缀
//第二个参数是一个函数,用来返回payload
export const addProductPost = createAsyncThunk('product/addProductPost', (item)=>{
   return  new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve(item)
       },3000)
   })
})

 在组件中 dispatch thunk

import React, { useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux'
import { addProductPost } from '../slices/productSlice'
//引入thunk函数
export default function Product() {
   const nameRef = useRef()
   const {list:productList,isLoading} = useSelector(state => state.product)
   const dispatch = useDispatch()
   const onAdd = () => {
       //thunk函数的使用,跟普通的action creator的使用一样
   
       dispatch(addProductPost({ name: nameRef.current.value }))
  }
   return (
       <div>
          我是商品页面<br />
          商品名:<input ref={nameRef} required /><br />
          {isLoading?<div>请求数据中...
</div>:productList.map((item, index) => <li key={index}>
              商品名:{item.name}
           </li>)}
           <button onClick={onAdd}>新增商品</button>
       </div>
  );

}

添加extraReducers
extraReducers可以监听createAsyncThunk创建的action被 dispatch。
 

//slices/productSlice.js
//创建slice
const slice = createSlice({
   //定义域名称
   name: 'product',
   //传入初始state
   initialState,
   //定义reducers
   reducers: {
       //这个reducer用来把商品数据存储到store中
       addProduct: (state, action) => {
           state.list.push(action.payload)
      },
       //这个reducer用来更改isLoading
       changeState:(state,action)=>{
           state.isLoading=action.payload
      }
  },
   //extraReducer设置createAsyncThunk创建的thunk被dispatch后的reducer处理器
   extraReducers(builder){
       builder
      .addCase(addProductPost.pending,(state,action)=>{
           state.isLoading=true
      })
      .addCase(addProductPost.fulfilled,(state,action)=>{
           state.isLoading=false
           state.list.push(action.payload)
      })
  }
})

createAsyncThunk(二)

//slices/productSlice.js
//创建获取商品数据的thunk
export const productListGet = createAsyncThunk('product/productListGet',
async () => {
   const data = await new Promise((resolve, reject) => {
       setTimeout(() => {
           resolve([{ name: '苹果' }, {name: '香蕉' }, { name: "蓝莓" }])
      }, 3000)
  })
   return data
})
extraReducers(builder) {
       builder
          .addCase(addProductPost.pending,(state, action) => {
               state.isLoading = true
          })
          .addCase(addProductPost.fulfilled, (state,action) => {
               state.isLoading = false
              state.list.push(action.payload)
          })
          .addCase(productListGet.pending, (state, action) => {
               state.isLoading = true
          })
          .addCase(productListGet.fulfilled, (state, action) => {

               return { list: action.payload, isLoading: false }
          })
          .addCase(productListGet.rejected, (state,action) => {
               state.isLoading=false
          })
  }
//pages/Product.js
import { addProductPost, productListGet } from '../slices/productSlice'
//组件挂载后请求商品数据
useEffect(() => {
       dispatch(productListGet())
  }, [])

性能优化

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

//pages/ProductChild.js
import React, { useEffect } from 'react';
function ProductChild() {
 
   useEffect(() => {
       console.log('子元素重新渲染')
  })
   return (
       <div>
          子元素
   </div>
  );
}
export default React.memo(ProductChild)

为了让子组件跳过没有必要的渲染,我们可以将 子组件包装在 React.memo() 中,这可以确保组件只有在 props 真正更改时才会重新渲染。
 

//pages/ProductChild.js
export default React.memo(ProductChild)

createSelector

 如果子组件中使用了useSelector来获取数据,也会存在一些不必要的渲染。

import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
function ProductChild() {
    const list=useSelector(state=>state.product.list.filter(item=>item.name.length>2))
   useEffect(() => {
       console.log('子元素重新渲染')
  })
   return (
       <div>
          子元素
   </div>
  );
}
export default React.memo(ProductChild)

我们可以使用 createSelector 来定义有记忆的选择器。
 

//slices/productSlice.js
import { createSelector} from '@reduxjs/toolkit'
export const selectList= createSelector([state =>{    

   return state.product.list
} ], (list) => {
   console.log('重新计算list')
   return list.filter(item=>item.name.length>2)
})

//pages/ProductChild.js
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import {selectList} from '../slices/productSlice'
function ProductChild() {
   // const list=useSelector(state=>state.product.list.filter(item=>item.name.length>2))
  const list=useSelector(selectList)
 
   useEffect(() => {
       console.log('子元素重新渲染')
  })
   return (
       <div>
          子元素
   </div>
  );
}
export default React.memo(ProductChild)
举报

相关推荐

0 条评论