优雅的在React项目中使用Redux的方法

或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处

首先我们会用到哪些框架和工具呢?

React
UI框架
Redux
状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux
react-redux
React插件,作用:方便在React项目中使用Redux
react-thunk
中间件,作用:支持异步action

|--src
  |-- store        Redux目录
    |-- actions.js
    |-- index.js
    |-- reducers.js
    |-- state.js
  |-- components      组件目录
    |-- Test.jsx
  |-- App.js        项目入口

准备工作

第1步:提供默认值,既然用Redux来管理数据,那么数据就一定要有默认值,所以我们将state的默认值统一放置在state.js文件:

// state.js

// 声明默认值
// 这里我们列举两个示例
// 同步数据:pageTitle
// 异步数据:infoList(将来用异步接口获取)
export default {
  pageTitle: '首页',
  infoList: []
}

第2步:创建reducer,它就是将来真正要用到的数据,我们将其统一放置在reducers.js文件

// reducers.js

// 工具函数,用于组织多个reducer,并返回reducer集合
import { combineReducers } from 'redux'
// 默认值
import defaultState from './state.js'

// 一个reducer就是一个函数
function pageTitle (state = defaultState.pageTitle, action) {
 // 不同的action有不同的处理逻辑
 switch (action.type) {
  case 'SET_PAGE_TITLE':
   return action.data
  default:
   return state
 }
}

function infoList (state = defaultState.infoList, action) {
 switch (action.type) {
  case 'SET_INFO_LIST':
   return action.data
  default:
   return state
 }
}

// 导出所有reducer
export default combineReducers({
  pageTitle,
  infoList//
//

第3步:创建action,现在我们已经创建了reducer,但是还没有对应的action来操作它们,所以接下来就来编写action

// actions.js

// action也是函数
export function setPageTitle (data) {
 return (dispatch, getState) => {
  dispatch({ type: 'SET_PAGE_TITLE', data: data })
 }
}

export function setInfoList (data) {
 return (dispatch, getState) => {
  // 使用fetch实现异步请求
  window.fetch('/api/getInfoList', {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    }
  }).then(res => {
    return res.json()
  }).then(data => {
    let { code, data } = data
    if (code === 0) {
      dispatch({ type: 'SET_INFO_LIST', data: data })
    }
  })
 }
}

最后一步:创建store实例

// index.js

// applyMiddleware: redux通过该函数来使用中间件
// createStore: 用于创建store实例
import { applyMiddleware, createStore } from 'redux'

// 中间件,作用:如果不使用该中间件,当我们dispatch一个action时,需要给dispatch函数传入action对象;但如果我们使用了这个中间件,那么就可以传入一个函数,这个函数接收两个参数:dispatch和getState。这个dispatch可以在将来的异步请求完成后使用,对于异步action很有用
import thunk from 'redux-thunk'

// 引入reducer
import reducers from './reducers.js'

// 创建store实例
let store = createStore(
 reducers,
 applyMiddleware(thunk)
)

export default store

至此,我们已经完成了所有使用Redux的准备工作,接下来就在React组件中使用Redux

开始使用

首先,我们来编写应用的入口文件APP.js

// App.js

import React from 'react'
import ReactDOM from 'react-dom'

// 引入组件
import TestComponent from './components/Test.jsx'

// Provider是react-redux两个核心工具之一,作用:将store传递到每个项目中的组件中
// 第二个工具是connect,稍后会作介绍
import { Provider } from 'react-redux'
// 引入创建好的store实例
import store from '@/store/index.js'

// 渲染DOM
ReactDOM.render (
 (
  <div>
    {/* 将store作为prop传入,即可使应用中的所有组件使用store */}
    <Provider store = {store}>
     <TestComponent />
    </Provider>
  </div>
 ),
 document.getElementById('root')
)

最后是我们的组件:Test.jsx

// Test.jsx

import React, { Component } from 'react'

// connect方法的作用:将额外的props传递给组件,并返回新的组件,组件在该过程中不会受到影响
import { connect } from 'react-redux'

// 引入action
import { setPageTitle, setInfoList } from '../store/actions.js'

class Test extends Component {
 constructor(props) {
  super(props)
 }

 componentDidMount () {
  let { setPageTitle, setInfoList } = this.props

  // 触发setPageTitle action
  setPageTitle('新的标题')

  // 触发setInfoList action
  setInfoList()
 }

 render () {
  // 从props中解构store
  let { pageTitle, infoList } = this.props

  // 使用store
  return (
   <div>
    <h1>{pageTitle}</h1>
    {
      infoList.length > 0 ? (
        <ul>
          {
            infoList.map((item, index) => {
              <li>{item.data}</li>
            })
          }
        </ul>
      ):null
    }
   </div>
  )
 }
}

// mapStateToProps:将state映射到组件的props中
const mapStateToProps = (state) => {
 return {
  pageTitle: state.pageTitle,
  infoList: state.infoList
 }
}

// mapDispatchToProps:将dispatch映射到组件的props中
const mapDispatchToProps = (dispatch, ownProps) => {
 return {
  setPageTitle (data) {
    // 如果不懂这里的逻辑可查看前面对redux-thunk的介绍
    dispatch(setPageTitle(data))
    // 执行setPageTitle会返回一个函数
    // 这正是redux-thunk的所用之处:异步action
    // 上行代码相当于
    /*dispatch((dispatch, getState) => {
      dispatch({ type: 'SET_PAGE_TITLE', data: data })
    )*/
  },
  setInfoList (data) {
    dispatch(setInfoList(data))
  }
 }
}

export default connect(mapStateToProps, mapDispatchToProps)(Test)

Redux三大原则

单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中

State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象

使用纯函数来执行修改
为了描述 action 如何改变 state tree ,你需要编写 reducers

结语

感谢您的观看,以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux react-redux React插件,作用:方便在React项目中使用Redux react-thunk 中间件,作用:支持异步action 目录结构 Tips:与Redux无关的目录已省略 |--src |-- store Redux目录

  • React/Redux应用使用Async/Await的方法

    Async/Await是尚未正式公布的ES7标准新特性.简而言之,就是让你以同步方法的思维编写异步代码.对于前端,异步任务代码的编写经历了 callback 到现在流行的 Promise ,最终会进化为 Async/Await .虽然这个特性尚未正式发布,但是利用babel polyfill我们已经可以在应用中使用它了. 现在假设一个简单的React/Redux应用,我将引入 Async/Await 到其代码. Actions 此例子中有一个创建新文章的 Action ,传统方法是利用 Prom

  • 简单介绍react redux的中间件的使用

    用过react的同学都知道在redux的存在,redux就是一种前端用来存储数据的仓库,并对改仓库进行增删改查操作的一种框架,它不仅仅适用于react,也使用于其他前端框架.研究过redux源码的人都觉得该源码很精妙,而本博文就针对redux中对中间件的处理进行介绍. 在讲redux中间件之前,先用两张图来大致介绍一下redux的基本原理: 图中就是redux的基本流程,这里就不细说. 一般在react中不仅仅利用redux,还利用到react-redux: react-redux这里也不细说.

  • 优雅的在React项目中使用Redux的方法

    或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux react-redux React插件,作用:方便在React项目中使用Redux react-thunk 中间件,作用:支持异步action |--src |-- store Redux目录 |-- actions.js |-- index.js |-- reducers.js |-

  • React项目中使用Redux的 react-redux

    目录 背景 UI 组件 容器组件 connect() mapStateToProps() mapDispatchToProps() 组件 实例:计数器 背景 在前面文章一文理解Redux及其工作原理中,我们了解到redux是用于数据状态管理,而react是一个视图层面的库 如果将两者连接在一起,可以使用官方推荐react-redux库,其具有高效且灵活的特性 react-redux将组件分成: 容器组件:存在逻辑处理 UI 组件:只负责现显示和交互,内部不处理逻辑,状态由外部控制 通过redux

  • 如何在React项目中优雅的使用对话框

    目录 背景 场景一 场景二 场景三 问题一:难以扩展 问题二:维护问题 问题的本质 对话框的本质 全局的状态管理的对话框 整体的架构 具体实现 Redux - reducer 存储 Redux - action 处理对话框的显示隐藏 Hook - useCommonModal 创建对话框-容器模块 对话框返回值处理 运行实例 总结 参考 背景 对话框在前端开发应用中,是一种非常常用的界面模式.对话框作为一个独立的窗口,常常被用于信息的展示,输入信息,亦或者更多其他功能.但是项目的使用过程中,在某

  • TypeScript在React项目中的使用实践总结

    序言 本文会侧重于TypeScript(以下简称TS)在项目中与React的结合使用情况,而非TS的基本概念.关于TS的类型查看可以使用在线TS工具

  • React项目中axios的封装与API接口的管理详解

    目录 前言 安装 引入 环境的切换 请求拦截 响应拦截 api的统一管理 总结 前言 在react项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中.他有很多优秀的特性,例如拦截请求和响应.取消请求.转换json.客户端防御XSRF等.如果还对axios不了解的,可以移步axios文档. 安装 //使用npm安装 npm install axios; //使用yarn安装 yarn add axios 引入 在项目

  • React项目中hook实现展示对话框功能

    目录 思路:使用全局状态管理所有对话框 尝试设计一个API去做对话框的全局管理 实现:创建NiceModal组件和相关API 处理对话框的返回值 总结 React中使用对话框并不容易,主要因为: 对话框需要在父组件中声明,才能在子组件中控制其是否显示 给对话框传递参数只能由props传入,这意味着所有状态管理都必须在更高阶的组件中.而实际上这个对话框的参数只在子组件中才会维护.这时就需要我们使用自定义事件将参数传回 这些问题的本质就是:如何用一个统一的方式去管理对话框,从而让对话框相关的业务逻辑

  • 在React项目中使用TypeScript详情

    目录 项目目录及ts文件划分 在项目中使用TypeScript具体实践 组件声明 React Hooks使用 useState useRef useCallback useMemo useContext useReducer useImperativeHandle Axios请求/响应定义封装 前言: 本文主要记录我如何在React项目中优雅的使用TypeScript,来提高开发效率及项目的健壮性. 项目目录及ts文件划分 由于我在实际项目中大部分是使用umi来进行开发项目,所以使用umi生成的

  • 在 React 项目中全量使用 Hooks的方法

    目录 前言 React Hooks useState useReducer 基础用法 进阶用法 useContext useEffect useLayoutEffect useRef useImperativeHandle useCallback useMemo React Redux Hooks useSelector useDispatch React Router Hooks useHistory useLocation useParams useRouteMatch 参考 结语 前言 此

  • 在react项目中使用antd的form组件,动态设置input框的值

    问题: 创建账号时,输入账号后不搜索直接保存,提示查询后,再点搜索就不能搜索这个账号了 原因: 点击保存之后,对表单进行了验证,导致之后请求的数据无法在更新到input框中,也就是说即使在state中有值,也不会更新initialValue值,就导致搜索后的值不能正确填入input中,表单也就提交不了. 解决办法: 不使用initialValue设置动态更新的值,而是使用 this.props.form.setFieldValue({name:data}); 用于动态更新值,就可以解决了. if

随机推荐