在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本章主要讲解redux在React项目中的应用。Redux官方文档。 一、基本概念Actionaction简单理解就是对象字面量。功能上来说就是把数据从应用传到store的有效载荷,和Vue中Mutation提交载荷类似。 有action创造函数,是一个生成action的方法。下面就是一个简单的同步actin: export function setGlobalState(data: {}) { return {type: 'SET_GLOBAL_STATE', data} } action生成后,store并没有生成或者发生变化,只是说明我要更新store了。怎么更新需要通过reducer函数来处理。 Reducerreducer本质上是纯函数,接受oldState、action两个参数,返回newState。reducer告诉开发系统是怎么更新store的。 function global(state: Global, action: any) { switch(action.type) { case 'SET_GLOBAL_STATE': return action.data default: return InitGlobalState } } reducer支持组合和拆分,可以根据项目业务合理进行组织。 Storestore就是项目中的数据流,将action和reducer联系起来。Redux应用只有一个store,起职责如下:
下面我们初始化一个store import { createStore } from 'redux' // 初始化store const Store = createStore( rootReducer, ) 二、React中使用Reduxredux是一种状态管理通用实现方案,可以应用在许多地方,并不受库的限制。react-redux正是两者搭配起来实现的通用库。 yarn add react-redux Provider全局注入store然后通过react-redux提供的Provider组件实现store注入。 import Store from './store' import { Provider } from 'react-redux' ReactDOM.render( <Provider store={Store}> <App/> </Provider>, document.getElementById('root') as HTMLElement //类型断言 ); 这样项目中的所有组件都能访问到store中state,并且通过dispatch来更新state。总之,store在项目中是单独存在的一个整体,作为数据源存在。而项目外部可以获取state,改变store中state的唯一方法就是dispatch(action)。 组件中使用store下面我们一todo.tsx组件为例,介绍组件中是如何获取、更新state的。 import { connect } from 'react-redux' const mapStateToProps = (state:InitState) => { return { todos: state.todos } } const mapDispatchToProps = (dispatch:Dis) => { return { onAddTodo(value: string) { dispatch(addTodo(value)) } } } Provider组件将store注入到组件中的本质,还是将store通过组件的props关联到每个组件上。接下来我们将两个map函数绑定到组件的属性上。 interface Props { todos: [] onAddTodo:(value: string) => void } interface State { value: string } class Todo extends React.Component<Props, State> { constructor(props: Props) { super(props) this.state = { value: '' } } handleAddTodo = () => { this.props.onAddTodo(this.state.value) this.setState({ value: '' }) } handleInputChange = (e: any) => { const { value } = e.target this.setState({ value }) } render () { return( <div> <Input value={this.state.value} placeholder="请输入清单项" onChange={this.handleInputChange}/> <Button onClick={this.handleAddTodo}>添加</Button> <ul> {this.props.todos.map((todo: any) => ( <li>{todo.text}</li> ))} </ul> </div> ) } } export default connect( mapStateToProps, mapDispatchToProps )(Todo) 这样我们就实现了在组件内部获取state,并且通过界面交互可以动态新增待办清单,更新store,最后实时渲染页面的功能。 三、redux高级用法组合拆分reducer之前有讲到可以拆分reducer,做到单一功能模块对应一个reducer。类似于Vuex中将store分成多个子modules。 redux提供的combineReducers方法即可接受多个reducer。 import { createStore, combineReducers } from 'redux' import Todo from './todo/reducers' import Ware from './ware/reducers' const rootReducer = combineReducers( Object.assign({}, Todo, Ware) ) 然后将rootReducer传入createStore中即可。 action中间件中间件MiddleWare可以在我们进行disatch时,更加细粒化的跟踪store的变化,并且允许我们建立异步action。 下面我们来看react-thunk中间件的作用,使用middleWare后,action创建函数除了返回action对象外,还能返回函数。这个函数会被react-thunk执行,在函数内部能执行更多操作,执行异步请求、dispatch action。 yarn add react-thunk 下面我们来修改下store/index.tsx文件: import thunkMiddleware from 'redux-thunk' import { createStore, applyMiddleware, combineReducers } from 'redux' const Store = createStore( rootReducer, applyMiddleware( thunkMiddleware, ) ) 现在我们的action创造函数中就能像下面这样写: export function addTodo(text: string) { return { type: 'ADD_TODO', text } } export function asyncAddTodo(text: string) { return (dispatch:Dis, getState: Get) => { if (checkStoreTodo(getState(),text)) { // 在 thunk 里 dispatch 另一个 thunk! return dispatch(addTodo(text)) } else { // 告诉调用代码不需要再等待。 return Promise.resolve() } } } 还有react-logger提供的中间件,在本地开发时在进行dispatch时,能打印改动日志。不仅如此,我们还可以自定义middleWare,用来实现自己想要的逻辑效果。 现在redux在react中一些基本用法都介绍完毕了,react中的一些第三方库基本和TypeScript结合的很好,可能有时候回调函数的参数不知道如何进行类型定义。有个d.ts文件则能在开发时进行智能提示,这个文件主要是在ts文件以js文件发布后,用来标记js文件里面对应的类型。 TypeScript官方文档有兴趣的朋友可以看看。 题外话,redux使用起来有点复杂。安利另外一个状态管理方案MobX,并且在react得到很好的实现,真正做到了开箱即用,代码写到哪里就在哪里使用! 这是一个系列文章: 从零搭建React+TypeScript的后台项目(一)--构建基础React+TypeScript项目 从零搭建React+TypeScript的后台项目(二)--后台router实现方案 从零搭建React+TypeScript的后台项目(三)--Redux基本配置 |
请发表评论