概念

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

React

UI框架

Redux

状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux

react-redux

React插件,作用:方便在React项目中使用Redux

react-thunk

中间件,作用:支持异步action

目录结构

Tips:与Redux无关的目录已省略

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

准备工作

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

/**
* 步骤一
* state.js
* 设置默认值
* yarn add redux
* yarn add react-redux
* yarn add redux-thunk
*/ // 声明默认值
// 这里我们列举两个示例
// 同步数据:pageTitle
// 异步数据:infoList(将来用异步接口获取)
export default {
pageTitle: '首页',
infoList: []
}

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

/**
* 步骤二
* reducers.js
* 创建 reducer
*/ // 工具函数,用于组织多个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
*/ // action也是函数
export function setPageTitle (data) {
return (dispatch, getState) => {
dispatch({
type: 'SET_PAGE_TITLE',
data: data
});
}
} export function setInfoList (data) {
return (dispatch, getState) => {
// 测试接口
let url = 'http://localhost:8000/user';
// 使用fetch实现异步请求
window.fetch(url, {
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
* 创建store实例
*/ // 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

开始使用

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

/**
* 入口文件
* index.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);
this.state = {};
} // 生命周期--组件加载完毕
componentDidMount () {
// 组件传值
let { setPageTitle, setInfoList } = this.props; // 触发setPageTitle action
setPageTitle('新的标题'); // 触发setInfoList action
setInfoList();
} render() {
// 通过mapStateToProps的映射,从props中解钩store
let { pageTitle, infoList } = this.props; // 使用 store
return (
<div>
<h1>{pageTitle}</h1>
{
infoList.length > 0 ? (
<ul>
{
infoList.map((item, index) => {
return (
<li key={item.id}>{item.name}</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

结语

以上就是在React项目中使用Redux的简单示例,文中代码可能会有编写错误,欢迎指正,同事希望本文对大家有所帮助

参考

效果图

优雅的在React项目中使用Redux的更多相关文章

  1. 如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...

  2. 如何在非 React 项目中使用 Redux

    本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...

  3. 在react项目中使用redux or mobx?

    主要比较参数: 库体积,打包项目体积 开发体验 性能对比 在对比参数前首先分析一下redux和mobx的设计模式,redux和mobx都没有使用传统的mvc/mvvm形式,而且他们使用flux结构也略 ...

  4. redux在react项目中的应用

    今天想跟大家分享一下redux在react项目中的简单使用 1 1.redux使用相关的安装 yarn add redux yarn add react-redux(连接react和redux) 2. ...

  5. react项目中引入了redux后js控制路由跳转方案

    如果你的项目中并没有用到redux,那本文你可以忽略 问题引入 纯粹的单页面react应用中,通过this.props.history.push('/list')就可以进行路由跳转,但是加上了redu ...

  6. 深入浅出TypeScript(5)- 在React项目中使用TypeScript

    前言 在第二小节中,我们讨论了利用TypeScript创建Web项目的实现,在本下节,我们讨论一下如何结合React创建一个具备TypeScript类型的应用项目. 准备 Webpack配置在第二小节 ...

  7. react项目中实现元素的拖动和缩放实例

    在react项目中实现此功能可借助 react-rnd 库,文档地址:https://github.com/bokuweb/react-rnd#Screenshot .下面是实例运用: import ...

  8. React项目中实现右键自定义菜单

    最近在react项目中需要实现一个,右键自定义菜单功能.找了找发现纯react项目里没有什么工具可以实现这样的功能,所以在网上搜了搜相关资料.下面我会附上完整的组件代码. (注:以下代码非本人原创,具 ...

  9. React项目中使用Mobx状态管理(二)

    并上一节使用的是普通的数据状态管理,不过官方推荐使用装饰器模式,而在默认的react项目中是不支持装饰器的,需要手动启用. 官方参考 一.添加配置 官方提供了四种方法, 方法一.使用TypeScrip ...

随机推荐

  1. git 出现 The current branch is not configured for pull No value for key branch.master.merge found in configuration

    以下是我在网上找到的不错的文章,我参考后已解决我的问题: http://my.oschina.net/robinsonlu/blog/144085 http://www.cnblogs.com/zha ...

  2. 前端入门22-讲讲模块化 包括webstrom建立简单ES6

    https://www.cnblogs.com/dasusu/p/10105433.html

  3. tomcat修改编码格式

    在TOMCAT中的conf文件夹下server.xml中的 <Connector中添加两个设置useBodyEncodingForURI="true" //设置POST和GE ...

  4. opencv读图片错误,已解决

    could not loag image... terminate called after throwing an instance of 'cv::Exception' what(): OpenC ...

  5. springboot Tomcat connector configured to listen on port 8081 failed to start.

    启动报 Tomcat connector configured to listen on port 8081 failed to start.   The port may already be in ...

  6. JavaSE-21 字符编码简介

    ASCII ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英 ...

  7. Windows下如何使用CMD命令进入MySQL数据库

    1.打开[开始]>[运行]输入[cmd]单击[确定]后出现CMD命令黑色窗口,这就是我们说的CMD命令行,或者使用快捷键Windows键(在键盘上有个Windows标志的按键)+R输入cmd后回 ...

  8. 如何判断页面是在移动端还是PC端打开的呢

    1. window.location.href = /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent) ? " ...

  9. PyQt5+requests实现车票查询工具

    PyQt5+requests实现一个车票查询工具,供大家参考,具体内容如下 结构图   效果图   思路 1.search(QPushButton)点击信号(clicked)连接到自定义的槽函数(ev ...

  10. 牛客练习赛29 B 列队

    [题解] 把某一行或某一列有4个1的都统计出来,然后首尾接上尽量长的,注意首尾不能选上同一个矩阵,要维护前缀.后缀1最大值和次大值. 还要注意维护矩阵内连续1的长度,因为可能有 0 0 0 0 这种情 ...