# React-base-redux **Repository Path**: lisa_zhu2012/React-base-redux ## Basic Information - **Project Name**: React-base-redux - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-02-21 - **Last Updated**: 2020-12-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React-base-redux #### 介绍 了解redux在react里的基础运用 #### 软件架构 软件架构说明 #### 项目搭建及上传gitee 1. npm install create-react-app -g 2. create-react-app react-project 安装的时候提示我node版本过低 (npm install -g n) 3. cd react-project npm install 4. npm run eject(当我们要进行二次配置的时候,需要找到node_modules文件夹里的react-scripts进行配置,但是当我们执行**npm run eject**就可以将配置文件抽出,方便开发配置) 5. npm run start 6. git init 7. git remote add origin https://gitee.com/lisa_zhu2012/react-project.git 8. git add . / git commit -m '' / git push -u origin master (or git push --set-upstream origin master) #### 项目依赖下载 1. npm install node-sass -D 2. npm install redux -S #### [redux 基础知识](http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html) ![redux](./public/redux.jpg) React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两个方面,它没涉及。 * 代码结构 * 组件之间的通信 > 2014年 Facebook 提出了 Flux 架构的概念,引发了很多的实现。2015年,Redux 出现,将 Flux 与函数式编程结合一起,很短时间内就成为了最热门的前端架构。 **如果你不知道是否需要 Redux,那就是不需要它** **只有遇到 React 实在解决不了的问题,你才需要 Redux** 简单说,如果你的UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。 * 用户的使用方式非常简单 * 用户之间没有协作 * 不需要与服务器大量交互,也没有使用 WebSocket * 视图层(View)只从单一来源获取数据 需要使用redux的项目: * 用户的使用方式复杂 * 不同身份的用户有不同的使用方式(比如普通用户和管理员) * 多个用户之间可以协作 * 与服务器大量交互,或者使用了WebSocket * View要从多个来源获取数据 > 上面这些情况才是 Redux 的适用场景:多交互、多数据源。 从组件层面考虑,什么样子的需要redux: * 某个组件的状态,需要共享 * 某个状态需要在任何地方都可以拿到 * 一个组件需要改变全局状态 * 一个组件需要改变另一个组件的状态 redux的设计思想: 1. Web 应用是一个状态机,视图与状态是一一对应的。 2. 所有的状态,保存在一个对象里面(唯一数据源)。 ##### redux的流程: 1.store通过reducer创建了初始状态 2.view通过store.getState()获取到了store中保存的state挂载在了自己的状态上 3.用户产生了操作,调用了actions 的方法 4.actions的方法被调用,创建了带有标示性信息的action 5.actions将action通过调用store.dispatch方法发送到了reducer中 6.reducer接收到action并根据标识信息判断之后返回了新的state 7.store的state被reducer更改为新state的时候,store.subscribe方法里的回调函数会执行,此时就可以通知view去重新获取state > 注意:flux、redux都不是必须和react搭配使用的,因为flux和redux是完整的架构,在学习react的时候,只是将react的组件作为redux中的视图层去使用了。 reducer必须是一个纯函数: **Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。** 纯函数是函数式编程的概念,必须遵守以下一些约束。 * 不得改写参数 * 不能调用系统 I/O 的API * 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果 由于 Reducer 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变 State,必须返回一个全新的对象,请参考下面的写法。 ``` // State 是一个对象 function reducer(state, action) { return Object.assign({}, state, { thingToChange }); // 或者 return { ...state, ...newState }; } // State 是一个数组 function reducer(state, action) { return [...state, newItem]; } ``` 最好把 State 对象设成只读。你没法改变它,要得到新的 State,唯一办法就是生成一个新对象。这样的好处是,任何时候,与某个 View 对应的 State 总是一个不变的对象。 我们可以通过在createStore中传入第二个参数来设置默认的state,但是这种形式只适合于只有一个reducer的时候 ### redux 详细开发流程及扩展 1. 下载redux工具 **npm i redux -S** 2. 创建store const store = createStore(reducer) 3. 创建reducer纯函数 ``` const reducer = (state = _state, action) => { let new_state = Object.assign({}, state) switch ( action.type ) { case ADD_NEW_TODO: new_state.todos.push(action.todo);break; case REMOVE_TODO: new_state.todos = action.todos;break; default:break; } //同步一下本地存储 localStorage.todos = JSON.stringify(new_state.todos) //reducer一定要返回状态 return new_state } export default reducer ``` 4. 为store挂载默认状态 为reducer的state参数设置默认值,再返回出新的state,这样的话,store就有state了 5. 组件使用store的state 组件通过调用store.getState()来获得store中的state 6. 创建actionCreator actionCreator里的方法,作用是执行一些自定逻辑之后,创建一个带有标识性信息的action,交由reducer处理 store.dispatch(action) 7. 在reducer中,根据action上的标识信息做出判断之后,返回一个新状态,这个时候store里的状态已经更改了 8. 让组件去获取最新的状态 在组件的初始化阶段的生命周期钩子函数中给store.subscribe传入回调函数,当状态更改的时候这个回调函数就会触发,在这个回调里就可以让组件获取最新的状态之后进行setState,当然,如果发现所用的状态没有更改可以做出判断来决定是否进行setState #### reducer划分 当我们协同开发的时候,或者项目独立功能模块较多的时候,把状态放在一个reducer中处理的话会导致更新维护比较麻烦 在这里我们研究将store进行模块化的管理 actionCreator、state本身与store耦合度很低,最主要的是把reducer拆分开 我们可以利用combindReducers函数,将分离开的renducer整合成一个,这样的话,需要注意的是在使用的时候,state也会根据划分的reducer有一个不同的分布(因为一个应用中只能有一个大的state,这样的话reducer中的代码将会特别特别的多,那么就可以使用combineReducers方法将已经分开的reducer合并到一起) ``` import { combineReducers } from 'redux' //引入分开的reducer import todos from './todos/reducer' //将分开的reducer合并在一起,形成一个整体的reducer const reducer = combineReducers({ todos }) export default reducer ``` 注意: 1. 分离reducer的时候,每一个reducer维护的状态都应该不同 2. 通过store.getState获取到的数据也是会安装reducers去划分的 3. 划分多个reducer的时候,默认状态只能创建在reducer中,因为划分reducer的目的,就是为了让每一个reducer都去独立管理一部分状态