react-redux初级教程,纯白话讲述redux数据、开发流程整理,redux数据持久化实现
以下文章均为个人近期所学心得,自学react、redux,逐渐找到自己的方向,现将自己的方向方式写出来,以供大家学习参考,肯定会有不足,欢迎批评指正。
日常项目直接使用react是完全没有问题的,可是随着项目的日益壮大,组件数量的逐渐增长,组件之间的嵌套使得数据的管理越来越繁重。
纯react项目,每个组件自己维护自己的state,父子组件之间通信、兄弟组件通信也都可以做到,只不过随时项目代码量的增加后期会变得难以维护,所以使用redux这种数据管理是很有必要的,而且也是自我技术水平提高的一个很好方向。
本文专注功能实现、使用流程,所以可能细节问题点阐述的不够深,不过个人觉得用于初学者使用并且达到想要的功能应该可以满足了。
首先原理(纯白话):
页面操作(点击啊什么的)触发action -->
action做一层处理后触发reducer -->
reducer中定义全局的唯一的store中的state+存入的方法(必须是纯函数,也就是说你传入什么参数就输出相应的结果,不可以根据实时时间戳啊等类似的方法产出不同的值。) -->
最后数据保存进了store中的state,页面也会根据state的改变自动更新。
基本: Provider:具体概念不赘述,想细研究的自行度娘,这里只说明放在根组件的最外层并将store传递进去 <Provider store={store}> <Component /> </Provider>
代码(登录功能流程):
// 使用react-redux中的connect方法 import { connect } from 'react-redux'; // 导入我们定义的action import { saveUserinfo } from '@/Reducers/Pages/actions'; // 使用connect包裹我们的state和action,这里有两个方法(mapStateToProps、mapDispatchToProps),具体概念自行度娘 // 组件结尾导出处 export default connect(mapStateToProps, mapDispatchToProps)(Login); // 可以写成 export default connect(state => ({ // 如果你的组件需要使用store中的state,就在这里引入你所以要使用的reducer函数名 }), { // 这里引用你当前组件所需要使用的所有action方法 saveUserinfo })(Login); // 按钮提供一个点击事件 <button onClick={this.sumitForm}>登录</button> // sumitForm方法 sumitForm = () => { var username = this.refs.username.value; var password = this.refs.password.value; // 发送ajax请求,这里我封装一层,很简单,可以直接写ajax请求,主要点在请求成功的回调里 LoginFunc(username,password) .then(res => { // 请求成功后的数据 var data = res.data; // 这里就是触发action的地方,只需要将我们需要的数据作为参数传进去就好 this.props.saveUserinfo(data); this.props.history.push("/index"); }) }
以上就是我们在组件中触发action的过程,到这里你就可以将接口返回来的数据传递给action了
// 定义action时需要先定义action-type,作用就是关联action和reducer,action想要触发reducer那么只需要使用定义的type就可以,不需要去引用reducer,这样别人在看我们的代码时,看type就知道这一块有哪些功能了,具体的注释也可以写在type中。 // type很简单 // 保存用户信息 export const SAVEUSERINFO = "SAVEUSERINFO";
action代码
// 导入type import * as Pages from './action-types'; // 保存用户表单数据 export const saveUserinfo = (data) => { // 这个传进来的data就是我们刚刚在组件中传递进来的后端返回数据 // 这里直接returntypes,并将data传递过去 return { type: Pages.SAVEUSERINFO, data } }
这里就是action,我们可以将组件中的后端请求写在action里,只需要返回的时候触发type并将数据传递过去就好
下面我们看reducer
// 之前说了,action只需要触发type就可以触发reducer了 // 所以reducer中同样需要引入reducer import * as Pages from './action-types'; // 在reducer中我们需要定义state,也是就是唯一store中的state let defaultValue = { session_id: "", user_name: "", user_id: "", is_login: false, initialization: "", org_name: "" } // reducer中就是将action传递过来的数据保存到store中的state里 // 两个参数,第一个是state,第二个是action传递过来的数据,包含type和数据,通过type值判断执行那个函数,这里只定义了一个type export default function UserInfo (state = defaultValue, action = {}) { switch (action.type) { // 这个就是type也就是action和reducer关联的type case Pages.SAVEUSERINFO: return { ...state, // 这里就是将action传递过来的数据保存到我们的store中 ...{ session_id: action.data.data.session_id, user_name: action.data.data.name, user_id: action.data.data.id, is_login: true, initialization: action.data.data.initialization, org_name: action.data.data.org_name } }; default: return state; } }
以上就完成了我们从后端拿数据,保存到store中的所有流程。
// 保存到了store中后,我们页面的所有组件都可以拿这里边的数据, // 同样,我们组件中用到数据的地方会根据store中数据的改变而改变,也就是说我们想要改变页面的状态,唯一的办法就是触发action完成以上步骤。
到这里我们还没有结束,需要我们形成闭环,也就是怎么将store存入我们的Provider
// 我这里是将store拆分了,按功能去拆分的,具体可以看每个人的习惯去拆分
我的目录结构,可根据具体项目区自定自己的目录结构
// 有拆分就要有合并,所以我们要在存入Provider之前进行reducer的合并 // 这里使用redux提供的方法combineReducers import { combineReducers, } from 'redux'; import UserInfo from './Pages/reducers'; const rootReducer = combineReducers({ UserInfo, // 一些其他功能的reducer // UserStaffDirectory, // addUserMsgReducer }); // 导出统一的reducer export default rootReducer;
插一句,以上就已经完成了基本功能,这里我在多加一项功能,就是数据持久化,也就是我们数据存到store中但是会存在一个刷新数据丢失的问题,这样很不利与我们项目的使用,所以我加入一个新的库,来保证我们的数据是可持久化的,这里使用redux-persist库
数据持久化
// 首先导入redux的一些方法 import { createStore, applyMiddleware } from 'redux'; // 还使用了thunk,还没来的及去研究,这里先使用吧 import thunk from 'redux-thunk'; // 引入redux-persist import { persistStore, persistReducer } from 'redux-persist'; import { PersistGate } from 'redux-persist/es/integration/react'; import storage from 'redux-persist/es/storage' // 首先定义一个对象(按官方文档来的,没具体研究) const persistConfig = { key: 'root', storage, }; // 将我们的合并后的reducer引入 import Reducers from '@/Reducers'; // 使用redux-persist合并 const persistedReducer = persistReducer(persistConfig, Reducers) // 定义一个函数,返回persistor和store,让我的组件使用 function configureStore(){ // 这里我使用了thunk,具体原理我也没去细研究,使用redux的createStore去合并,最终产出我们需要传入Provider的store let store = createStore(persistedReducer, applyMiddleware(thunk)); // 这里就是应用redux-persist以完成数据持久化 let persistor = persistStore(store); return { persistor, store } } // 组件render中 const render = Component => { // 引入 const { persistor, store } = configureStore(); ReactDOM.render( // 将store传入跟组件 <Provider store={store}> // 数据持久化 <PersistGate persistor={persistor}> // 所有子组件 <Component /> </PersistGate> </Provider>, document.getElementById('app'), ) }
以上就完成了全部循环,组件发起action,触发reducer,保存数据到store中,组件被更新。
只有存的步骤,不能没有取,对吧,上文中实现了登录功能,并且将后端返回的数据保存到store中,现在我们将store中的数据拿出来展示在界面上。
登录请求成功后后端会返回用户名,用户ID等信息,我们已经将其保存到了store中,下面看我们的header组件将引用我们store中的用户名。
不需要我们引入过多的文件,只需要在组件结尾处的方法mapStateToProps加入我们要的reducer函数名即可
const mapStateToProps = state => ({ UserInfo: state.UserInfo }) export default connect(mapStateToProps,({}))(Header); // 组件中使用 this.props.UserInfo.user_name // 即可取值 // 同时呢,我们改变了store中的user_name那么我们取值的地方也会动态更新。
以上就是本文全部内容,如有发现不足,或错误之处,烦请指正。
转载请注明出处,SF大洋首发。