zoukankan      html  css  js  c++  java
  • 从零搭建React+TypeScript的后台项目(三)

    本章主要讲解redux在React项目中的应用。Redux官方文档

    一、基本概念

    Action

    action简单理解就是对象字面量。功能上来说就是把数据从应用传到store的有效载荷,和Vue中Mutation提交载荷类似。

    有action创造函数,是一个生成action的方法。下面就是一个简单的同步actin:

    export function setGlobalState(data: {}) {
        return {type: 'SET_GLOBAL_STATE', data}
    }

    action生成后,store并没有生成或者发生变化,只是说明我要更新store了。怎么更新需要通过reducer函数来处理。

    Reducer

    reducer本质上是纯函数,接受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支持组合和拆分,可以根据项目业务合理进行组织。

    Store

    store就是项目中的数据流,将action和reducer联系起来。Redux应用只有一个store,起职责如下:

    • 维持应用的 state;
    • 提供 getState() 方法获取 state;
    • 提供 dispatch(action) 方法更新 state;
    • 通过 subscribe(listener) 注册监听器;
    • 通过 subscribe(listener) 返回的函数注销监听器。

    下面我们初始化一个store

    import { createStore } from 'redux'
    
    // 初始化store
    const Store = createStore(
      rootReducer,
    )

    二、React中使用Redux

     redux是一种状态管理通用实现方案,可以应用在许多地方,并不受库的限制。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基本配置 

  • 相关阅读:
    python中的编码问题
    CVPR2018 Tutorial 之 Visual Recognition and Beyond
    hdu 1376 Octal Fractions
    hdu 1329 Hanoi Tower Troubles Again!
    hdu 1309 Loansome Car Buyer
    hdu 1333 Smith Numbers
    hdu 1288 Hat's Tea
    hdu 1284 钱币兑换问题
    hdu 1275 两车追及或相遇问题
    hdu 1270 小希的数表
  • 原文地址:https://www.cnblogs.com/lodadssd/p/12588759.html
Copyright © 2011-2022 走看看