Redux 三大原则
单一数据源
整个应用程序的
state
只存储在一个store
中 Redux 并没有强制让我们不能创建多个Store
,但是那样做并不利于数据的维护 单一的数据源可以让整个应用程序的state
变得方便维护、追踪、修改
State 是只读的
唯一修改 State 的方法一定是触发
action
,不要试图在其他地方通过任何的方式来修改 State; 这样就确保了 View 或网络请求都不能直接修改 state,它们只能通过 action 来描述自己想要如何修改 stat; 这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心 race condition(竟态)的问题;
使用纯函数来执行修改
通过 reducer 将旧 state 和 action 联系在一起,并且返回一个新的 State; 随着应用程序的复杂度增加,我们可以将 reducer 拆分成多个小的 reducers,分别操作不同 state tree 的一部分; 但是所有的 reducer 都应该是纯函数,不能产生任何的副作用
什么是纯函数
返回结果只依赖于它的参数,并且在执行过程里面没有副作用
纯函数
function sum(num1, num2){ return num1 + num2; }
const num1 = 10; function sum(num2){ return num1 + num2; }
非纯函数
let num1 = 10; function sum(num2){ return num1 + num2; }
官方文档:https://www.redux.org.cn/docs/introduction/ThreePrinciples.html
安装
安装稳定版:
npm install --save redux
index.js:
const redux = require('redux'); // 定义一个状态 let initialState = { count: 0 }; // 利用 store 来保存状态(state) const store = redux.createStore(reducer); // 利用 action 来修改状态 const addAction = {type: 'ADD_COUNT', num: 1}; const subAction = {type: 'SUB_COUNT', num: -1}; // 利用 reducer 将 store 和 action 串联起来 function reducer(state = initialState, action) { switch (action.type) { case 'ADD_COUNT': return {count: state.count + action.num}; case 'SUB_COUNT': return {count: state.count - action.num}; default: return state; } }
监听状态的改变
store.subscribe(() => { console.log(store.getState()); });
从 Store 中获取存储的状态
console.log(store.getState());
修改 Store 中存储的状态
store.dispatch(addAction);
上面的处理方式实是存在问题的主要问题有以下几点:
- store、action、reducer 代码都写在一个文件中,不利于维护(后续文章解决)
- action 和 reducer 中都是使用字符串来指定和判断操作类型,写错不报错(本文当中进行解决)
- action 中的操作写死了,不够灵活(本文解决)
第二点的解决方案可以利用常量解决,第三点的解决方案可以利用函数解决,优化之后的代码如下:
const redux = require('redux'); const ADD_COUNT = 'ADD_COUNT'; const SUB_COUNT = 'SUB_COUNT'; // 定义一个状态 let initialState = { count: 0 }; // 利用store来保存状态(state) const store = redux.createStore(reducer); // 利用action来修改状态 const addAction = (num) => { return {type: ADD_COUNT, num: num}; }; const subAction = (num) => { return {type: SUB_COUNT, num: num}; }; // 利用reducer将store和action串联起来 function reducer(state = initialState, action) { switch (action.type) { case ADD_COUNT: return {count: state.count + action.num}; case SUB_COUNT: return {count: state.count - action.num}; default: return state; } }
监听状态的改变
store.subscribe(() => { console.log(store.getState()); });
从 Store 中获取存储的状态
console.log(store.getState());
修改 Store 中存储的状态
store.dispatch(addAction(5)); store.dispatch(subAction(5));
综合运用(在React中使用)
上面文章当中说明了一个问题需要解决,在本文主要介绍的就是这个问题的解决方案;
- store、action、reducer 代码都写在一个文件中,不利于维护
这个问题呢,可以在项目工程当中新建一个 store 文件夹,在该文件夹当中分别创建 action.js
,constants.js
,reducer.js
,store.js
等文件:
- action.js
import { ADD_COUNT, SUB_COUNT } from './constants'; // 利用action来修改状态 export const addAction = (num) => { return {type: ADD_COUNT, num: num}; }; export const subAction = (num) => { return {type: SUB_COUNT, num: num}; };
- constants.js
export const ADD_COUNT = 'ADD_COUNT'; export const SUB_COUNT = 'SUB_COUNT';
- reducer.js
import { ADD_COUNT, SUB_COUNT } from './constants'; // 定义一个状态 let initialState = { count: 666 }; // 利用reducer将store和action串联起来 function reducer(state = initialState, action) { switch (action.type) { case ADD_COUNT: return {count: state.count + action.num}; case SUB_COUNT: return {count: state.count - action.num}; default: return state; } } export default reducer;
- store.js
import {createStore} from 'redux'; import reducer from './reducer'; // 利用store来保存状态(state) const store = createStore(reducer); export default store;
使用 Redux
- App.js
import React from 'react'; import store from './store/store'; import {addAction, subAction} from './store/action'; class App extends React.PureComponent { constructor(props) { super(props); this.state = { count: store.getState().count } } componentDidMount() { store.subscribe(() => { this.setState({ count: store.getState().count }) }) } componentWillUnmount() { store.unsubscribe(); } render() { return ( <div> <p>{this.state.count}</p> <button onClick={() => { this.btnClick() }}> 增加 </button> </div> ) } btnClick() { store.dispatch(addAction(5)); } } export default App;
React-Redux-其它组件中使用
紧接着React-Redux-综合运用(在React中使用)的内容,下面介绍的是 Redux 在其它组件当中的使用以及注意点,在 src 目录下创建一个 component 目录在目录当中创建一个 home 与 about 组件,里面的内容是基于 app.js 进行参考得到的如下:
- Home.js
import React from 'react'; import store from '../store/store'; import {addAction} from '../store/action'; class Home extends React.PureComponent { constructor(props) { super(props); this.state = { count: store.getState().count } } componentDidMount() { store.subscribe(() => { this.setState({ count: store.getState().count }) }) } componentWillUnmount() { store.unsubscribe(); } render() { return ( <div> <p>{this.state.count}</p> <button onClick={() => { this.btnClick() }}>递增 </button> </div> ) } btnClick() { store.dispatch(addAction(1)); } } export default Home;
- About.js
import React from 'react'; import store from '../store/store'; import {subAction} from '../store/action'; class About extends React.PureComponent { constructor(props) { super(props); this.state = { count: store.getState().count } } componentDidMount() { store.subscribe(() => { this.setState({ count: store.getState().count }) }) } componentWillUnmount() { store.unsubscribe(); } render() { return ( <div> <p>{this.state.count}</p> <button onClick={() => { this.btnClick() }}>递减 </button> </div> ) } btnClick() { store.dispatch(subAction(1)); } } export default About;
- App.js
import React from 'react'; import store from './store/store'; import {addAction} from './store/action'; import Home from './components/Home'; import About from './components/About'; class App extends React.PureComponent { constructor(props) { super(props); this.state = { count: store.getState().count } } componentDidMount() { store.subscribe(() => { this.setState({ count: store.getState().count }) }) } componentWillUnmount() { store.unsubscribe(); } render() { return ( <div> <p>{this.state.count}</p> <button onClick={() => { this.btnClick() }}> 增加 </button> <Home/> <About/> </div> ) } btnClick() { store.dispatch(addAction(5)); } } export default App;
- 测试结果:
经过如上的一顿操作过后,发现代码存在的问题,就是重复代码过多,不利于维护,还有其它的一些问题,这里先不列举在下一篇文章,博主会全部统一一一进行介绍,当然还可以引出一个新的知识点。
最后
本期结束咱们下次再见👋~
🌊 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ 💗