redux
Redux 和 useReducer 😍
一、Redux 的来头🤡
相信大家在写这个 todoList
的时候,发现这个玩意要比其他的难写,为什么嘞?
![大家应该都是这样简单拆分组件的吧(❁´◡`❁)](https://i2.100024.xyz/2024/02/04/kgsr53.webp)
可以看到,这个组件视觉上分为三个部分,但是这三个部分会相互影响, 这就导致如果设计不好的话,状态满天飞,组件间通信来通信去是个大问题。
看大家基本都想到把状态提升到全局来解决这个问题,这确实挺不错的😍
这其实就有一点类似于redux
的理念了: 找个地方专门管理状态,让组件内部逻辑更清晰,这在大工程里会相当相当有用
是不是不敢想象在组件外的状态会有多酷?🤩继续往下看吧
二、 Redux下载😊
还是老样子,npm梭哈
1 |
|
其实这个包可以不要的,这个包超级麻烦👽
redux
官方也注意到这个问题,于是就出了一个小甜甜:@reduxjs/toolkit
来取代这位牛夫人
1npm install @reduxjs/toolkit
现在更推荐这个哇🐶
如果要在咱的react
项目中用,还得下一个react-redux
包
1 |
|
三、Redux文件结构👾
传统Redux
结构
src/
|– actions/
| |– counterActions.js
|– reducers/
| |– counterReducer.js
|– store/
| |– configureStore.js
|– components/
| |– Counter.js
| |– App.js
|– index.js
都什么年代了,还在玩传统redux
?😓
有了redux-toolkit
之后,那可是变了天了
src/
|– slices/
| |– counterSlice.js
|– store/
| |– configureStore.js
|– components/
| |– Counter.js
| |– App.js
|– index.js
可以看到,多出来一个slices
,少掉了reducer
和action
,这是因为toolkit
中的slices
把这两个功能自动搞好了,这样我们写起来也超级方便,超级爱😍
四、redux
用法💩
首先,使用
createSlice
方法,创建一个slice
, 包括它的- 名称
name
, - 初始状态
initialState
, action
的创建函数reducers
(不知道为啥要叫reducer
根本就不沾一点边😡)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import {createSlice, PayloadAction} from "@reduxjs/toolkit";
import {itemType} from "../pages/listType.ts";
import {autoKey} from "../utils/geneKeys.ts";
const listInfoSlice = createSlice({
name: 'listInfo',
initialState: [] as itemType[],
reducers: {
add: (state: itemType[], action: PayloadAction<string>) => {
return state.concat({
value: action.payload,
key: autoKey.next().value as number,
isCompleted: false,
});
},
dele: (state: itemType[], action: PayloadAction<number>) => {
return state.filter((item) => item.key != action.payload)
},
...
}
})
export const listActions = listInfoSlice.actions
export default listInfoSlice.reducer传参数可以看到是通过
action
传递的,可以指定参数类型,相当不错- 名称
然后,通过
configureStore
创建一个store
来管理存储这个state
1
2
3
4
5
6
7
8
9
10
11
12import {configureStore} from "@reduxjs/toolkit";
import listInfoReducer from "../slices/listInfoSlice.ts";
import displayReducer from "../slices/displaySlice.ts";
const todoStore = configureStore({
reducer: {
listReducer: listInfoReducer,
displayReducer: displayReducer
}
})
export default todoStore什么,你问我之后?🤕之后就直接开耍了啊,给你们摘一段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42// listItem.tsx
export const ListItem: React.FC<listItemProps> = (props) => {
const [edit, setEdit] = useState<boolean>(false);
const {key, value, isCompleted} = props.itemInfo;
const dispatch = useDispatch();
const handleCheck = () => {
dispatch(listActions.toggle(key))
}
const handleDelete = () => {
dispatch(listActions.dele(key))
}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const handleEdit = (e) => {
if(e.keyCode === 13) {
dispatch(listActions.edit([key, e.target.value]))
e.target.value = ''
setEdit(false)
}
}
const handleBlur = () => {
setEdit(false)
}
const handleDoubleClick = () => {
setEdit(true)
}
return (
<>
<li className={isCompleted?'completed':'active'} onDoubleClick={handleDoubleClick}>
{!edit
? <div className="view">
<input className="toggle" onChange={() => null} type="checkbox" checked={isCompleted} onInput={handleCheck}/>
<label>{value}</label>
<button className="destroy" onClick={handleDelete}></button>
</div>
: <input type='text' onKeyDown={handleEdit} onBlur={handleBlur} autoFocus className='new-todo'></input>
}
</li>
</>
)
}
五、常用hook
🤣
1. useDispatch
在上边的也看到了,就是一个分配工作的小包工头
1 |
|
通过dispatch
,把action
传递给store
,更新state
2. useSelector
这位更是重量级,负责摘出store
中对应的state
比如这是我们的store
:
1 |
|
我们可以这样拿到list
的值:
1 |
|
不过之所以说它重量级是因为它不太搞得懂ts
,所以经常要自己去创建类型喂给她,比如这里:storeType
就是自己定义的:
1 |
|
六、useReducer
🥳
这玩意就是react
看到redux
的成功,模仿出来的一个hook
,可以理解为redux
青春版, 听完redux
之后这个就是小case
啦
1 |
|