我是一个多年的Vue的使用者,我经常使用Vue + Vue-Router + Vuex来开发单页面应用,那么当切换到React框架时,这一切都变得不一样了,首先Vue和React之间的区别不是很大,都是用来实现UI的库,Router的区别有一些,到状态管理这边,React有Redux、Mobx等多种解决方案,相比Vue的Vuex来说着实是复杂些,Vuex更加简单容易理解。
今天我们就通过简单易懂大白话的方式来理解Redux究竟是做什么的?
为什么要有Redux
首先React和Vue一样,都是对DOM的一层抽象,并没有像Angular一样提供整套的Web开发解决方案。它们都缺乏代码结构、组件通信方案。而对于大型复杂应用来说,这两点又非常重要,所以只使用Vue和React没办法写大型应用。
为了解决问题,2014年Facebook提供Flux架构的概念,2015年Redux出现,将Flux架构和函数式编程结合,很快成为了前端的热门架构方案。
你可能不需要 Redux
这句话放在Vuex上也是适用的,Redux和Vuex都是解决一类问题而出现的架构方案,我们很多时候并不必须使用它们。
曾经有人说过
“如果你不知道是否需要 Redux,那就是不需要它。”
Redux 的创造者 Dan Abramov 又补充了一句。
“只有遇到 React 实在解决不了的问题,你才需要 Redux 。”
如果UI非常简单,没有过多的交互,我们其实并不需要Redux,使用它反而会增加复杂性
如果我们的多个组件的状态需要被共享、一个组件的状态更改可以使其他组件的状态也被改变,这时我们就需要使用Redux或者其他状态管理工具。
上面我们提到了Flux,如果不明白Flux也没有关系,它不耽误我们理解Redux,如果感兴趣可以去查看文档。
Redux 有很好的文档,当然本文目的是通过简单的方式说明Redux的用处和用法,如果要深入探究还是要去查看文档。
在React中使用Redux
Redux是一个单独的库,如果要将Redux用在React项目中我还需要react-redux这个库,用来将Redux和React进行连接。
我们要先来安装下面的依赖:
npm i @reduxjs/toolkit react-redux
假设我们要用Redux来实现一个计数器,创建counterSlice.js用来管理计数器的状态:
import {
createSlice } from '@reduxjs/toolkit';
export const slice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
export const {
increment, decrement, incrementByAmount } = slice.actions;
export const incrementAsync = amount => dispatch => {
setTimeout(() => {
dispatch(incrementByAmount(amount));
}, 1000);
};
export const selectCount = state => state.counter.value;
export default slice.reducer;
然后创建store.js,引入我们刚才创建的计数器模块,然后创建出计数器store
import {
configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export default configureStore({
reducer: {
counter: counterReducer,
},
});
然后在index.js中引入store并使用Provider组件注入
import App from './App';
import store from './app/store';
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
之后就是在组件或者页面中去获取和操作store中的状态数据
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
decrement,
increment,
incrementByAmount,
incrementAsync,
selectCount,
} from './counterSlice';
import styles from './Counter.module.css';
export function Counter() {
const count = useSelector(selectCount);
const dispatch = useDispatch();
const [incrementAmount, setIncrementAmount] = useState('2');
return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
</div>
<div className={styles.row}>
<input
className={styles.textbox}
aria-label="Set increment amount"
value={incrementAmount}
onChange={e => setIncrementAmount(e.target.value)}
/>
<button
className={styles.button}
onClick={() =>
dispatch(incrementByAmount(Number(incrementAmount) || 0))
}
>
Add Amount
</button>
<button
className={styles.asyncButton}
onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
>
Add Async
</button>
</div>
</div>
);
}
- 使用useSelector方法找到我们想要的状态数据
- 使用useDispatch()来触发我们对状态的操作
完整的例子请看:https://codesandbox.io/s/github/reduxjs/redux-essentials-counter-example/tree/master/?from-embed
最后
一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新