目錄
Redux Toolkit
redux toolkit的基本使用
RTK代碼模塊化
RTK QUERY的使用
useQuery參數
Redux Toolkit
Redux Toolkit是Redux的工具包,簡稱RTK,可以幫助我們處理使用Redux過程中的重復性工作,簡化Redux中的各種操作,當然博主也不可能將RTK講解的面面俱到,看完本篇文章后還是推薦大家多多看一下 官方文檔 ,無論是RTK還是Redux,在React中使用 react-redux 都是必不可少的,所以使用RTK依然需要安裝兩個包,如下:
npm install react-redux @reduxjs/toolkit
redux toolkit的基本使用
官方已經給出我們使用redux toolkit的基本示例了,如下圖所示,在這里我結合官方給出的示例簡單的說明并講解一下函數的使用。
根據官方給出的基礎案例,在src文件夾下新建文件夾store,然后新建index.jsx文件,并寫出如下代碼:
// 使用RTK創(chuàng)建store, createSlice 創(chuàng)建reducer的切片
import { configureStore, createSlice } from "@reduxjs/toolkit";
const stuSlice = createSlice({ // 需要一個配置對象作為參數,通過對象的不同屬性來指定它的配置
name:'stu', // 用來自動生成 action 中的 type
initialState:{ // state的初始值
name:"張三",
age:18,
gender:"男",
address:"北京"
},
// 指定state的各種操作,直接在對象中添加方法
reducers:{
setName: state => { // state是一個代理對象,可直接修改
state.name = "李四"
},
setAge: state => {
state.age = 28
}
}
})
// 切片對象會自動的幫助我們生成action
export const { setName,setAge } = stuSlice.actions
// 創(chuàng)建store,用來創(chuàng)建store對象,需要一個配置對象作為參數
const store = configureStore({
reducer:{
student:stuSlice.reducer
}
})
export default store
要想在全局使用store文件中定義的數據和方法,需要在入口文件main.js文件中進行如下操作:
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './store'
ReactDOM.createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
)
接下里通過調用redux相關api來獲取數據和方法。
import { useSelector,useDispatch } from "react-redux"
import { setName,setAge } from "./store"
const App = () => {
// useSelector() 用來加載state中的數據
const student = useSelector(state => state.student)
// 通過useDispatch() 來獲取派發(fā)器對象
const dispatch = useDispatch()
const changeName = () =>{
dispatch(setName())
}
const changeAge = () =>{
dispatch(setAge())
}
return (
<div>
<p>{student.name}--{student.age}--{student.gender}--{student.address}</p>
<button onClick={changeName}>修改名字</button>
<button onClick={changeAge}>修改年齡</button>
</div>
)
}
export default App
如果想通過傳參的方式進行修改數據的話,可以采用以下這種方式:
RTK代碼模塊化
因為state的數據可能不止一種,將每一種數據都存放在store的一個文件中就會顯得代碼特別的臃腫,后期難以維護,為了便于今后的管理,可以對RTK代碼進行模塊化劃分,也就是說,每一個數據都有單獨的文件,最后所有的文件都整合到store文件夾下的index文件中,如下:
將我設置好的兩個store數據單獨抽離出去:
import { createSlice } from "@reduxjs/toolkit";
// 創(chuàng)建學生切片
const stuSlice = createSlice({ // 需要一個配置對象作為參數,通過對象的不同屬性來指定它的配置
name:'stu', // 用來自動生成 action 中的 type
initialState:{ // state的初始值
name:"張三",
age:18,
gender:"男",
address:"北京"
},
// 指定state的各種操作,直接在對象中添加方法
reducers:{
setName: (state,action) => { // state是一個代理對象,可直接修改
state.name = action.payload
},
setAge: (state,action) => {
state.age = action.payload
}
}
})
// 切片對象會自動的幫助我們生成action
export const { setName,setAge } = stuSlice.actions
export const { reducer:stuReducer } = stuSlice
import { createSlice } from "@reduxjs/toolkit";
// 創(chuàng)建學校切片
const schoolSlice = createSlice({
name:"school",
initialState:{
name:'北京大學',
address:'北京市',
},
reducers:{
setName: (state,action) => {
state.name = action.payload
},
setAddress: (state,action) => {
state.address = action.payload
}
}
})
export const { setName,setAddress } = schoolSlice.actions
export const { reducer:schoolReducers } = schoolSlice
將抽離出去的數據都存放在store文件夾下的index.jsx文件中,如下:
// 使用RTK創(chuàng)建store,用于管理所有數據的文件
import { configureStore } from "@reduxjs/toolkit";
import { stuReducer } from "./student";
import { schoolReducers } from "./school";
// 創(chuàng)建store,用來創(chuàng)建store對象,需要一個配置對象作為參數
const store = configureStore({
reducer:{
student:stuReducer,
school:schoolReducers
}
})
export default store
在相關組件中調用該store中的數據:
import { useSelector,useDispatch } from "react-redux"
import { setName,setAge } from "./store/student"
import { setAddress,setName as setSchoolName } from "./store/school"
const App = () => {
// useSelector() 用來加載state中的數據
const { student,school } = useSelector(state => state)
// 通過useDispatch() 來獲取派發(fā)器對象
const dispatch = useDispatch()
const changeName = () =>{
dispatch(setName("王五"))
}
const changeAge = () =>{
dispatch(setAge(30))
}
const changeSchoolName = () =>{
dispatch(setSchoolName("五道口職業(yè)技術學院"))
}
const changeSchoolAddress = () =>{
dispatch(setAddress("海淀區(qū)"))
}
return (
<div>
<h2>個人信息:</h2>
<p>{student.name}--{student.age}--{student.gender}--{student.address}</p>
<button onClick={changeName}>修改個人名字</button>
<button onClick={changeAge}>修改個人年齡</button>
<h2>學校信息:</h2>
<p>{school.name}--{school.address}</p>
<button onClick={changeSchoolName}>修改學校名字</button>
<button onClick={changeSchoolAddress}>修改學校地址</button>
</div>
)
}
export default App
可以看到上文進行抽離的代碼給人的感覺是十分干練整潔的,十分便于維護,結果如下:
RTK QUERY的使用
RTK不僅幫助我們解決了state問題,同時它還為我們提供了RTK Query用來幫助我們處理數據加載問題,RTK Query是一個強大的數據獲取和緩存工具,在它的幫助下,Web應用中的加載變得十分簡單,它使我們不再需要自己編寫虎丘數據和緩存數據的邏輯。
要知道在Web應用中加載數據時需要處理的問題
1)根據不同的加載狀態(tài)顯示不同的UI組件
2)減少對相同數據重復發(fā)送請求
3)使用樂觀更新,提示用戶體驗
4)在用戶與UI交互時,管理緩存的聲明周期
這些問題RTKQ都可以幫助我們處理,首先可以直接通過RTKQ向服務器發(fā)送請求加載數據,并且RTKQ會自動對數據進行緩存,避免重復發(fā)送不必要的請求,其次RTKQ在發(fā)送請求時會根據請求不同的狀態(tài)返回不同的值,我們可以通過這些值來監(jiān)視請求發(fā)送的過程并隨時中止
RTKQ已經繼承在了RTK中,如果我們已經在項目中引入了RTK則無需再引入其余的模塊,如果你不想使用RTKQ給我們提供的發(fā)送請求的方式(簡單封裝過的fetch),需要自己引入要使用的發(fā)送請求的工具。ok接下來開始講解如何使用RTKQ,如下:
在store文件中新建一個word文件用于獲取名言警句的接口,如下:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
// 創(chuàng)建Api對象,createApi()用來創(chuàng)建RTKQ中的API對象
const wordApi = createApi({
reducerPath:'wordApi', // Api的標識,不能和其他的Api或reducer重復
baseQuery: fetchBaseQuery({ // 指定查詢的基礎信息,發(fā)送請求使用的工具
baseUrl:"https://api.uixsj.cn/"
}),
// build是請求的構造器,通過build來設置請求的相關信息
endpoints(build){
return {
getStudents:build.query({
query(){
// 用來指定請求的子路徑
return 'hitokoto/get'
}
})
}
}
})
// Api對象創(chuàng)建后,對象中會根據各種方法自動是生成對應的鉤子函數,通過這些鉤子函數,可向服務器發(fā)送請求
// 鉤子函數的命名規(guī)則 getStudents --> useGetStudentsQuery
export const { useGetStudentsQuery } = wordApi
export default wordApi
填寫完接口文件后,在store文件夾下的index.jsx文件中進行引入:
import { configureStore } from "@reduxjs/toolkit";
import wordApi from "./word";
const store = configureStore({
reducer:{
[wordApi.reducerPath]:wordApi.reducer
},
// 添加一個中間件,這個中間件已自動生成了我們直接引入即可,中間件用來處理Api緩存
middleware:getDefaultMiddleware => {
return getDefaultMiddleware().concat(wordApi.middleware)
}
})
export default store
當然這里的話我們也需要在入口文件中進行store傳入:
接下來開始使用我們創(chuàng)建的鉤子函數進行相關數據的調用,如下:
currentData:undefined? // 當前參數的最新數據
data:undefined????????????? // 最新的數據
isError:false????????????????? // 布爾值,是否有錯誤
error:Error()????????????????? // 對象,有錯時才存在
isFetching:true???????????? // 布爾值,數據是否在加載
isLoading:true????????????? // 布爾值,數據第一次加載成功
isSuccess:false??????????? // 布爾值,請求是否成功
isUninitialized:false????? // 布爾值,請求是否還沒有開始發(fā)送
refetch:f()???????????????????? // 一個函數,用來重新加載數據
status:"pending"????????? // 字符串,請求的狀態(tài)
因為我調用的接口沒有data數據,數據在error中,這里的話需要我們在error進行數據的獲?。?/p>
import { useGetStudentsQuery } from './store/word'
const App = () => {
// 調用Api查詢數據,這個鉤子函數它會返回一個對象作為返回值,請求過程中相關數據都在該對象中
const {isError,error,isLoading} = useGetStudentsQuery()
return (
<div>
{ isLoading && <p>數據加載中...</p> }
{isError && error.data}
</div>
)
}
export default App
如果接收的接口數據有很多,但自己只是想要其中的一小部分,可以通過以下方式解決:
useQuery參數
RTKQ給我們提供對接收到的數據進行自定義設置,如下:
import { useGetStudentsQuery } from './store/word'
const App = () => {
// 調用Api查詢數據,這個鉤子函數它會返回一個對象作為返回值,請求過程中相關數據都在該對象中
const result = useGetStudentsQuery(null,{
// useQuery可以接收一個對象作為第二個參數,通過該對象可以對請求進行配置
selectFromResult:result => { // 用來指定useQuery返回的結果
if(result.data === undefined){
result.data = '值被我修改了'
}
return result
},
pollingInterval:0, // 設置輪詢的間隔(隔一段時間發(fā)起一次請求),單位毫秒,如果為0則不輪詢
skip:false, // 設置是否跳過當前請求,默認為false
refetchOnMountOrArgChange:false, // 設置是否每次都重新加載數據,false正常使用緩存;true每次都重載數據;數字,數據緩存的時間(秒)
})
console.log(result)
const {isError,error,isLoading} = result
return (
<div>
{ isLoading && <p>數據加載中...</p> }
{isError && error.data}
</div>
)
}
還有兩個參數設置需要在store進行數據監(jiān)聽才能使用,如下:
文章來源:http://www.zghlxwxcb.cn/news/detail-428963.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-428963.html
到了這里,關于React--》Redux Toolkit的使用講解的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!