• 从零搭建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函数
    linux—shell 脚本编程
    python 内建函数
    列表解析式(List Comprehension)
    python标准库(datetime)
    python字典(dict)
    常用数据结构
    C 2010年笔试题
    C 2012年笔试题(保)
    C 2012年笔试题
  • 原文地址:https://www.cnblogs.com/lodadssd/p/12588759.html
Copyright © 2020-2023  润新知