- 文档翻译来的
- 用Typescript来的
- 不定期更新来的
环境配置,我看了一下,最好的配置方法是 npx create-react-app my-app --template redux-typescript
但问题是,我只是想在旧项目里添加redux。
我建议分两步走
- 旧项目用 Typescript基本模板
npx create-react-app my-app --template typescript
- 如果有需要,直接安装
react-redux @types/react-redux @reduxjs/toolkit
,注意,redux-toolkit已经包含了redux的 core。
快速开始
- 建立src/app/store.ts,并使用createStore建立 store、导出
import { configureStore } from "@reduxjs/toolkit";
const store= configureStore({
reducer:{}
})
export default store
我的理解,store就是存储数据的仓库,这个仓库里的数据可以供App使用,为了把数据传递给App,需要使用到Provider ,这个Provider类似Context.
2.到index.tsx中,找到App ,用Provider包裹它。
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
刚才建立了仓库,并把仓库里的数据传递给App,但问题是store还是空的,下面丰富仓库内容。
3. 到src/features/counter/counterSlice.ts 建立一个功能(feature),因为说到底store管理数据,这个数据不是一成不变的,肯定是和某个功能挂钩,比如增加或者减少数据就是一个功能
注意,刚才的store在app中,现在又是一个新的文件夹feature,
关于为什么叫slice,我的理解是一个store存储很多数据,对应很多功能,不可能统一编写,而应该slice成不同切片,方便写和改。
一个slice 起码需要name来作为标识,需要initialState来初始化状态,需要一个或者多个reducer(函数)来执行具体功能。
这里有个事儿,旧版本的redux需要手动定义action,用action来告诉store具体执行什么功能,新版本的redux-toolkit里边提供的createSlice API把这个简化了,
提供上面说的参数,自动给你创建action creator。
还有一点,redux旧版本需要采取“不变”的写法,新版的createSlice和createReducer用了Immer.js,所以写“mutable”那种形式的状态变化就可以。
name:描述和区分这个切片的功能
initialState:有初始值
reducers:包含一个或多个函数,函数就是实现功能的东东
import { createSlice } from "@reduxjs/toolkit";
export const counterSlice = createSlice({
name: "counter",
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
initialState: { value: 0 },
});
// 每个reducer对应的action creators 在这里就能自动创建 ,一个action creator就是创建一个对象的函数
//action 就是个对象,里边包含了具体要执行什么操作,比如“ADD” "SUBTRACT",还包括了所属的slice的名字
/*
比如这个就是一个action
{
"type": "counter/increment"
}
*/
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// 功能们
export default counterSlice.reducer;
好,现在store更丰富了,注意我们是从下向上地进行的操作,
store中肯定要包含数据和操作数据的功能,我们先通过slice的形式把数据和功能做好,随后加入到store即可。
通过在store的reducer中 以counter连接store和slice,因为之前说了name用于描述 还有 “区分”不同功能
app/store.ts
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice"
const store= configureStore({
reducer:{
//注意 counterReducer传入以后,用store.getState()就能获取对应数据
counter:counterReducer
}
})
export default store
好,现在有个问题,我们刚才就在store中集成了功能和数据,那这个特定slice的数据呢?总不能每次都手动从一堆数据里边找吧?(因为store势必会变得很复杂)
简单, rtk提供了useSelector来快速的(通过slice名字)选取你所需要的数据的这么一条美好的捷径吖。
那么又怎么传递功能到UI上面呢?也简单,还是rtk提供了 useDispatch功能,只要执行action creator,把结果传给useDispatch执行生成的dispatch函数,就行。
好,现在只要把数据和功能 和UI绑定就行了。
features/counter/Counter.tsx
import React, { ReactElement } from "react";
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement } from "../counter/counterSlice";
interface Props {}
export default function Counter({}: Props): ReactElement {
//数据,注意这个数据和slice中的name 是一致的
const count = useSelector((state) => (state as any).counter.value);
//功能,就是发射action
const dispatch = useDispatch();
return (
<div>
<div>count是: {count}</div>
<div
onClick={() => {
dispatch(increment());
}}
>
+
</div>
<div
onClick={() => {
dispatch(decrement());
}}
>
-
</div>
</div>
);
}
以上,我们建立了仓库,通过切片组织了一个功能和初始数据,在UI中用RTK提供的工具拿到数据,并且可以通过dispatch执行功能。
action被执行后,就会dispatch到store,store调用对应的reducer,并对应更新数据,store中数据变化,UI就会知晓并重新渲染。
建立仓库使用rtk提供的configureStore,具体配置以对象形式填写,成员变量必须包括一个reducer对象。
通过Provider提供数据给App。
使用createSlice来创建功能的数据的 分片。(这样很利于形成separation of concerns)
因为rtk内置了Immerse.js,直接写mutable形式就行。
建立分片后,别忘记导出action creator和 对应的reducer。
在UI中,通过rtk提供的 useDispatch 和useSelector 来获取执行功能的dispatcher和抓取特定数据。
标签:教程,redux,数据,reducer,功能,action,Redux,快速,store From: https://www.cnblogs.com/nulixuexipython/p/17095348.html