当前位置: 首页 > 编程日记 > 正文

redux-thunk使用教程

从无到有一步一步创建一个react-redux、redux-thunk使用教程:本教程GitHub地址:

https://github.com/chunhuigao/react-redux-thunk

创建react工程

在电脑上找一个文件夹,在命令窗使用create-react-app 创建我的react工程;这一步应该会的
create-react-app study-redux
复制代码
看到下面这个图证明我创建完毕

启动react服务

在创建任务完成后进入我的创建的react工程,然后npm start运行,接着在浏览器http://localhost:3000/我应用该可以看到下面图片的场景

安装redux

要使用redux我需要使用npm将redux包安装到我的react工程中
在react工程的命令窗输入
npm install redux
npm install react-redux
npm install redux-thunk
复制代码
如果报错,请使用淘宝代理cnpm安装。等待安装完毕,从新npm start启动项目

我的工程目录

删除无用的代码

将app.js中html结构代码删除,代码如下:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';class App extends Component {render() {return (<div className="App">{/* <header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a></header> */}</div>);}
}export default App;复制代码
这段代码对我学习redux没什么用,我喜欢代码简洁一点,所以删除了

创建第一个组件

在工程目录src/component中创建一个名为hello的文件夹,在hello文件夹中创建一个名为hello.js的文件。
在hello.js写如下代码:
import React, { Component } from 'react'class Hello extends Component {render() {return (<div><h2>学习redux</h2></div>)}
}
export default Hello
复制代码
在app.js中引入hello这个组件
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Hello from './component/hello/hello.js'
class App extends Component {render() {return (<div className="App"><Hello /></div>);}
}export default App;
复制代码
在浏览器中我应该可以看到“学习redux”这句文案了。

添加第一个事件

给hello添加一个按钮,点击按钮可以改变“学习redux”这句文案;hello.js具体代码如下:
import React, { Component } from 'react'
import './hello.css'class Hello extends Component {constructor(props){super(props)this.state = {title:'学习redux'}}changeTitle(){let title = '学习redux' + Math.ceil(Math.random()*100)this.setState({title:title})}render() {return (<div><h2>{this.state.title}</h2><button className="btn" onClick={()=>{this.changeTitle()}}>点击我改变标题</button></div>)}
}
export default Hello
复制代码

开始使用redux

下面这个流程刚开始接触redux可能云里雾里。但要坚持,跟着我的操作,你一定会看到结果的

index.js引用一下内容

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';import { Provider } from 'react-redux'  //新引入
import {createStore} from 'redux'   //新引入
import rootReducer from './rootReducer.js'  //新引入const store = createStore(rootReducer)
ReactDOM.render(
<Provider store={store}><App />
</Provider>
, document.getElementById('root'));// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();复制代码
redux和react-redux之前安装过,引用后会报错,原因是引入的rootReducer.js这个文件需要创建;

创建rootReducer

在src文件夹创建rootReducer.js文件代码如下:
文件中combineReducers将拆分的页面单独reducer合并为一个大的reducer
import {combineReducers} from 'redux'
import helloReducer from './component/hello/helloReducer.js'
const rootReducer = combineReducers({helloReducer
})
export default rootReducer
复制代码
这里面引入了一个helloReducer.js,这里我在hello.js同级文件夹创建helloReducer.js

创建helloReducer.js

reducer里面定义页面初始数据,在根据action.type操作state;具体代码如下:
const initState = {name:'hello,redux'
}
export default (state=initState,action) => {switch (action.type) {case 'CHANGE_NAME':return {...state,name:action.text}default:return state;}
}
复制代码
然后将reducer数据绑定到组件中,这里需要用到react-redux中的connect函数

数据绑定到组件

这部分是在hello.js中进行的;具体代码如下:
import React, { Component } from 'react'//引用connect
import {connect} from 'react-redux'import './hello.css'class Hello extends Component {constructor(props){super(props)this.state = {title:'学习redux'}}changeTitle(){let title = '学习redux' + Math.ceil(Math.random()*100)this.setState({title:title})}render() {
//此处打印this.props应该可以看到helloProp这个对象了,证明数据已经挂在到组件紫红console.log(this.props)let {prop} = this.propsreturn (<div><h2>{this.state.title}</h2><h3>我是来自redux数据{prop.name}</h3><button className="btn" onClick={()=>{this.changeTitle()}}>点击我改变标题</button></div>)}
}//mapStateToProps是connect一个参数, 作用到将store中的数据作为 props 绑定到组件上 
const mapStateToProps = (state, ownProps) => {return {helloProp: state.helloReducer//helloReducer是在rootReducer中的名}
}
//通过connect高阶函数绑定数据
export default connect(mapStateToProps)(Hello)
复制代码
数据已经绑定到组件了,怎么操作改变数据呢?需要用到action了

创建helloAction.js

在hello.js同级不目录创建helloAction.js;action主要负责发出动作指令,定义所有事件行为的;具体代码如下:
const helloAction = {changeName:(text)=>({type:"CHANGE_NAME",text:text,mate:'用于改变helloReducer中name值'})
}
export default helloAction
复制代码
文件创建好怎么用呢?数据可以绑定到组件,action也是可以绑定到组件的,使用redux中bindActionCreators,具体代码看hello.js

将action绑定到组件

在hello.js引入新创建的helloAction.js,哎,看代码吧
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
//引入helloAction
import helloAction from './helloAction.js'
import './hello.css'class Hello extends Component {constructor(props){super(props)this.state = {title:'学习redux'}}changeTitle(){let title = '学习redux' + Math.ceil(Math.random()*100)this.setState({title:title})}render() {//此处打印,应该可以看到actionsconsole.log(this.props)let {prop} = this.propsreturn (<div><h2>{this.state.title}</h2><h3>我是来自redux数据{prop.name}</h3><button className="btn" onClick={()=>{this.changeTitle()}}>点击我改变标题</button></div>)}
}const mapStateToProps = (state, ownProps) => {return {prop: state.helloReducer}
}//使用mapDispatchToProps绑定helloAction
const mapDispatchToProps = (dispatch, ownProps) => {return {actions:bindActionCreators(helloAction,dispatch)}
}
//将mapDispatchToProps作为参数给connect
export default connect(mapStateToProps,mapDispatchToProps)(Hello)
复制代码
改写changeTitle事件,修改redux传过来的数据
changeTitle(){let title = '学习redux' + Math.ceil(Math.random()*100)// this.setState({//   title:title// })let {actions} = this.propsactions.changeName(title)}
复制代码
效果图
孤例不为证,这个是在hello.js操作helloReducer的数据,不需要redux这么麻烦也可以搞定。下面我使用redux操作一下其他组件修改HelloReducer中的数据
移步GitHub点个start

创建other组件

在component文件夹中创建other文件夹,在other文件夹创建other.js;具体代码如下图
在app.js引入other.js
import React, { Component } from 'react';
import Hello from './component/hello/hello.js'
import Other from './component/other/other.js'
import './App.css';class App extends Component {render() {return (<div className="App"><Hello /><Other /></div>);}
}export default App;复制代码

other具体代码

import React, { Component } from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import helloAction from '../hello/helloAction.js'class Other extends Component {changeName(){let {helloAction} = this.props;let text = 'other' + (Math.random() *100)helloAction.changeName(text)}render() {let {otherProp} = this.propsconsole.log(this.props)return (<div><h3>我是其他组件</h3><button className="btn" onClick={()=>{this.changeName()}}>我是其他组件的按钮</button></div>)}
}const mapStateToProps = (state, ownProps) => {return {otherProp: state.helloReducer}
}
const mapDispatchToProps = (dispatch, ownProps) => {return {helloAction:bindActionCreators(helloAction,dispatch)}
}
export default connect(mapStateToProps,mapDispatchToProps)(Other)
复制代码
点击按钮,同样可以操作helloReducer.js的数据,mapStateToProps只能绑定一个数据源吗?如果other也有reducer怎么办呢?

组件上绑定多个数据

在other.js同级目录创建otherReducer.js具体代码如下:
const initState = {title:'我是otherReducer数据'
}export default (state=initState,action) => {switch (action.type) {case "CHANGE_TITLE":return {...state,title:action.text}default:return state}
}
复制代码
在rootReducer.js中引用otherReducer.js,rootReducer代码如下:
import {combineReducers} from 'redux'
import helloReducer from './component/hello/helloReducer.js'
import otherReducer from './component/other/otherReducer.js'
const rootReducer = combineReducers({helloReducer,otherReducer
})
export default rootReducer
复制代码
在other.js的mapStateToProps中绑定reducer数据
const mapStateToProps = (state, ownProps) => {return {helloProp: state.helloReducer,otherProp: state.otherReducer}
}
复制代码
在render打印this.props试试?
  render() {let {helloProp,otherProp} = this.propsconsole.log(this.props)return (<div><h3>我是其他组件</h3><button className="btn" onClick={()=>{this.changeName()}}>我是其他组件的按钮</button><div>{otherProp.title}</div></div>)}
复制代码
到此,可以使用redux了。但这写只能执行同步操作,异步操作需要要结合redux-thunk或者redux-saga了;

redux异步操作

也是写一个简单的例子
在index.js引入redux-thunk
//注释import {createStore} from 'redux' 
//新增
import {createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'//注释 const store = createStore(rootReducer)
//新增
const store = createStore(rootReducer,applyMiddleware(thunk))
复制代码
在component文件夹下创建example文件夹,在example文件夹创建example.js、exampleAction.js、exampleReducer.js具体代码如下:
example.js代码:
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import exampleAction from './exampleAction.js'
class Example extends Component {asyncFn(){let {exampleAction} = this.propsexampleAction.asyncThing()console.log(this.props)}render() {let {exampleProp} = this.propsreturn (<div><h3>异步操作</h3><h4>{exampleProp.text}</h4><button className='btn' onClick={()=>{this.asyncFn()}}>我要进行异步操作</button></div>)}
}
const mapStateToProps = (state, ownProps) => {return {exampleProp: state.exampleReducer}
}
const mapDispatchToProps = (dispatch, ownProps) => {return {exampleAction:bindActionCreators(exampleAction,dispatch)}
}
export default connect(mapStateToProps,mapDispatchToProps)(Example)
复制代码
exampleReducer.js代码:
const initState={text:'我是用来测试异步操作的',sign:null
}
export default (state=initState,action) =>{console.log(action)switch (action.type) {case 'SUCCESS':return {...state,text:action.text,sign:'success'}case 'ERROR':return {...state,text:action.text,sign:'error'}default:return state}
}
复制代码
exampleAction.js
 const exampleAction = {asyncThing:()=>{return (dispatch, getState) =>{// fetch('https://hacker-news.firebaseio.com/v0/jobstories.json')//     .then(res => {//         dispatch(exampleAction.asyncSuccess('我是成功回调'))  //     }).catch(e => {//         dispatch(exampleAction.asyncError('我是成功回调'))  // });setTimeout(() => {let sign = Math.random() >= 0.5 ? true : false;console.log(sign)sign ? dispatch(exampleAction.asyncSuccess('我是成功数据'))  : dispatch(exampleAction.asyncError('我是失败数据'))  }, 2000);}},asyncSuccess:(text)=>({type:'SUCCESS',text:text,mate:'异步成功操作'}),asyncError:(text)=>({type:'ERROR',text:text,mate:'异步成功操作'})
}
export default exampleAction
复制代码
exampleReducer.js同样需要引入rootReduder.js中。
rootReducer代码:
import {combineReducers} from 'redux'
import helloReducer from './component/hello/helloReducer.js'
import otherReducer from './component/other/otherReducer.js'
import exampleReducer from './component/example/exampleReducer.js'
const rootReducer = combineReducers({helloReducer,otherReducer,exampleReducer
})
export default rootReducer
复制代码
在app.js引入新建是example组件,应该可以看待如下界面
redux异步搞定了。

结束语:

不知我描述的清楚不清楚,希望这篇文章能不能帮到你。本人学识有限,如有文档中不规范或者误人子弟的错误言论,请指正。感谢你花时间阅读这篇文章,谢谢!




转载于:https://juejin.im/post/5c446a7a51882524b4074354

相关文章:

VLC SDK在VS2010中的配置及简单使用举例

1. 从http://www.videolan.org/vlc/download-windows.html下载vlc-2.2.0-win32.7z&#xff0c;解压缩&#xff1b;2. 新建一个VLCtest控制台工程&#xff1b;3. 将/vlc-2.2.0-win32/vlc-2.2.0/sdk/include添加到工程属性中&#xff0c;C/C -->General …

百万奖金悬赏AI垃圾分类,就问你来不来?

也许我们从来没有想过&#xff0c;看似简单的垃圾分类居然给“聪明”的人类带来如此大的困扰2019年7月1日&#xff0c;史称“最严格的垃圾分类法”《上海市生活垃圾管理条例》正式开始施行一夜之间上海人最常用的见面语从“侬好”变成了“侬是什么垃圾&#xff1f;”虽然只有可…

资质申报 - 系统集成企业资质等级评定条件(2012年修定版)

关于发布《计算机信息系统集成企业资质等级评定条件&#xff08;2012年修定版&#xff09;》的通知工信计资&#xff3b;2012&#xff3d;6号各省、自治区、直辖市、计划单列市工业和信息化主管部门、新疆生产建设兵团工业和信息化委员会、各级资质评审机构&#xff0c;各有关单…

@HostListener 可接收的事件列表

下面有一个文档详细介绍Angular 中的事件列表&#xff1a; https://github.com/angular/angular/blob/master/packages/compiler/src/schema/dom_element_schema_registry.ts#L78。 星号代表的是事件 (no prefix): property is a string.*: property represents an event.!: pr…

GraphSAGE: GCN落地必读论文

作者 | William L. Hamilton, Rex Ying, Jure Leskovec来源 | NIPS17导读&#xff1a;图卷积网络&#xff08;Graph Convolutional Network&#xff0c;简称GCN&#xff09;最近两年大热&#xff0c;取得不少进展。作为 GNN 的重要分支之一&#xff0c;很多同学可能对它还是一知…

Ubuntu14.04 32位上编译VLC2.2.0源码操作步骤

1. 首先安装必须的依赖软件&#xff0c;打开终端&#xff0c;执行&#xff1a;sudo apt-get install git libtool build-essential pkg-config autoconf2. 从 http://www.videolan.org/vlc/download-sources.html 下载vlc-2.2.0源码&#xff0c;将其存放到/home/spring/VLC目录…

根据PromiseA+规范实现Promise

Promise是ES6出现的一个异步编程的一个解决方案&#xff0c;改善了以往回调函数的回调地狱(虽然写起来也挺像的)。不会Promise的可以移步阮一峰的Promise&#xff0c;这里讲的非常清晰。 就现在的发展情况而言&#xff0c;Promise这种解决方案频繁的在我们的代码中出现&#xf…

黄浴:基于深度学习的超分辨率图像技术发展轨迹一览

作者 | 黄浴转载自知乎导读&#xff1a;近年来&#xff0c;使用深度学习技术的图像超分辨率&#xff08;SR&#xff09;取得了显著进步。本文中&#xff0c;奇点汽车自动驾驶首席科学家黄浴对基于深度学习技术的图像超分辨率技术进行了一次全面的总结&#xff0c;分析了这门技术…

Qt简介、安装及在Ubuntu14.04 32位上简单使用举例

Qt是一个跨平台的C图形用户界面应用程序开发框架。它既可以开发GUI程序&#xff0c;也可用于开发非GUI程序。Qt是面向对象的框架&#xff0c;很容易扩展。Qt是一个C工具包&#xff0c;它由几百个C类构成&#xff0c;你在程序中可以使用这些类。Qt具有OOP的所有优点。 跨平台的…

FOSCommentBundle功能包:设置Doctrine ODM映射(投票)

原文出处&#xff1a;12b-mapping_mongodb.md原文作者&#xff1a;FriendsOfSymfony授权许可&#xff1a;创作共用协议翻译人员&#xff1a;FireHare校对人员&#xff1a;适用版本&#xff1a;FOSCommentBundle 2.0.5文章状态&#xff1a;草译阶段Step 12b: Setup MongoDB mapp…

Python最大堆排序实现方法

Python最大堆排序实现方法&#xff0c;具体代码如下&#xff1a; # -*- coding: utf-8 -*- def merge_sort(seq, cmpcmp, sentinelNone): """合并排序&#xff0c;伪码如下&#xff1a; MERGE(A, p, q, r) 1 n1 ← q - p 1 // 前个子序列长度 2 …

内含福利 | 世界人工智能大会:对话大咖,深挖机器学习的商业应用

机器学习作为人工智能时代的关键技术突破&#xff0c;已经在日常生活中广泛应用&#xff0c;给用户带来便利。越来越多的企业也通过机器学习&#xff0c;解决生产和经营中的难题。传统制造业&#xff1a;应用机器学习&#xff0c;部署系统异常检测方案&#xff0c;预测组件寿命…

windows7 64位操作系统上使vs2010和vs2013能够并存的处理方法

之前机子上是只安装有vs2010&#xff0c;后来在没有卸载vs2010的情况下想装个vs2013,使vs2010与vs2013同时并存在windows764位机上。需要依次安装cn_visual_studio_ultimate_2013_x86_dvd_3009109.iso、vs2013.2.iso和vc_mbcsmfc.exe。在安装过程中遇到的问题有&#xff1a; (…

Spring Cloud Alibaba 基础教程:Nacos 生产级版本 0.8.0

Spring Cloud Alibaba 基础教程&#xff1a;Nacos 生产级版本 0.8.0 昨晚Nacos社区发布了第一个生产级版本&#xff1a;0.8.0。由于该版本除了Bug修复之外&#xff0c;还提供了几个生产管理非常重要的特性&#xff0c;所以觉得还是有必要写一篇讲讲这次升级&#xff0c;在后续的…

awk命令使用和取出数据的最大值,最小值和平均值

得到取出数据的最大值&#xff1a;cat manager.txt |grep monitor|awk {print$9}|sort -rn|head -1得到取出数据的最小值&#xff1a;cat manager.txt|grep monitor |awk {print $9}|sort -n|head -1得到取出数据的平均值&#xff1a;cat manager.txt|grep monitor |awk {print…

windows7 64位机上CUDA7.0配置及在VS2010中的简单使用举例

1. 查看本机配置&#xff0c;查看显卡类型是否支持NVIDIA GPU&#xff0c;选中计算机--> 右键属性 --> 设备管理器 --> 显示适配器&#xff1a;NVIDIA GeForce GT 610&#xff0c;从https://developer.nvidia.com/cuda-gpus可以查到相应显卡的compute capabili…

用友云平台,真正的云原生架构,加速云应用落地

数字化经济的出现&#xff0c;企业需要通过新技术实现数字化转型&#xff0c;完成企业管理和业务模式变革。而云计算是数字化中尤为重要且能够更快实现的技术手段。真正的云应用必须是基于云原生架构的&#xff0c;PaaS是一个重要的步骤&#xff0c;因为这是云原生的第一接触点…

从ACM班、百度到亚马逊,深度学习大牛李沐的开挂人生

“大神”&#xff0c;是很多人对李沐的印象。作为一经推出便大受追捧的 MXNet 深度学习框架的主要贡献者之一&#xff0c;李沐功不可没。值得注意的是&#xff0c;这个由 DMLC&#xff08;Distributed Machine Learning Community&#xff09;打造的深度学习框架&#xff0c;创…

Linux基础介绍

Linux的创始人Linus Torvalds。Linux的官方标准发音为[linəks]。Linux和Unix是非常像的&#xff0c;Linux就是根据Unix演变过来的。Linux是免费的&#xff0c;其实只是说Linux的内核免费。在Linux内核的基础上产生了众多的Linux版本。Linux的发行版说简单点就是将Linux内核与应…

Go在区块链的发展和演进

Go语言发展至今已经过去十年多了&#xff0c;是目前最流行的新兴语言&#xff0c;云计算领域的首选语言&#xff0c;而且目前随着区块链的流行&#xff0c;Go再次成为了这个领域的第一语言&#xff0c;以太坊&#xff0c;IBM的fabric等重量级的区块链项目都是基于Go开发。 原文…

一天掌握AI核心技术,上手应用,开发者该划哪些重点?

Alpha Go 只会下棋&#xff0c;却并不擅长垃圾分类&#xff1b;智能助手已经可以执行很多任务&#xff0c;但距离真正的人机自然交互还很远。如今 AI 的发展面临着诸多瓶颈&#xff0c;基础理论研究缺失&#xff0c;深度学习的黑箱属性无解&#xff0c;把一切托付于未知并不可靠…

学会这21条,你离Vim大神就不远了

来源 | Python编程时光&#xff08;ID: Python-Time&#xff09;导语&#xff1a;作者本人是 Vim 的重度使用者&#xff0c;就因为喜欢上这种双手不离键盘就可以操控一切的feel&#xff0c;Vim 可以让人对文本的操作更加精准、高效。对于未使用过 Vim 的朋友来说&#xff0c;可…

C 语言 和 C++语言的对比学习   二 数据类型

不管是什么语言&#xff0c;我们最习惯的是通过 “hello world” &#xff0c;来昭告世界&#xff0c;我们有了新的语言来向这个世界问好&#xff0c;尽管真正属于我们自己的其实是哭声。&#xff08;呵呵&#xff0c;笑点有点低&#xff09;&#xff0c;下面我们来介绍最为基础…

Makefile语法基础介绍

在Linux下&#xff0c;make是一个命令工具&#xff0c;是一个解释Makefile中指令的命令工具。make命令执行时&#xff0c;需要一个Makefile文件&#xff0c;以告诉make命令需要怎么样去编译和链接程序。 make如何工作&#xff1a;在默认的方式下&#xff0c;只输入make命令&am…

MaxCompute studio与权限那些事儿

背景知识 MaxCompute拥有一套强大的安全体系&#xff0c;来保护项目空间里的数据安全。用户在使用MaxCompute时&#xff0c;应理解权限的一些基本概念&#xff1a; 权限可分解为三要素&#xff0c;即主体&#xff08;用户账号或角色&#xff09;&#xff0c;客体&#xff08;表…

GitHub标星3w+的项目,全面了解算法和数据结构知识

作者 | 程序员小吴来源 | 五分钟学算法&#xff08;ID: CXYxiaowu&#xff09;导语&#xff1a;今天分享一个开源项目&#xff0c;里面汇总了程序员技术面试时需要了解的算法和数据结构知识&#xff0c;并且还提供了相应的代码&#xff0c;目前 GitHub 上标星 35000 star&#…

Shell脚本基础介绍

shell基础简介&#xff1a;编写脚本通常使用某种基于解释器的编程语言。而shell脚本不过就是一些文件&#xff0c;我们能将一系列需要执行的命令写入其中&#xff0c;然后通过shell来执行这些脚本。进入Linux系统(Ubuntu)&#xff0c;打开终端Terminal&#xff0c;”$”表示普通…

「小程序JAVA实战」小程序的举报功能开发(68)

转自&#xff1a;https://idig8.com/2018/09/25/xiaochengxujavashizhanxiaochengxudeweixinapicaidancaozuo66-2/ 通过点击举报按钮&#xff0c;跳转到举报页面完成举报操作。 后台开发 获取发布人的userId&#xff0c;videoId&#xff0c;创建者的Id controllerUserControlle…

tar常见文件解压法

2019独角兽企业重金招聘Python工程师标准>>> tar常见文件解压法:.gz - z 小写.bz2 - j 小写.xz - J 大写.Z - Z大写 转载于:https://my.oschina.net/open1900/blog/149238

cookie的作用域

当我们给网站设置cookie时&#xff0c;大家有没有发现在网站的其他域名下也接收到了这些cookie。这些没用的cookie看似不占多少流量&#xff0c;但如果对一个日PV千万的站点来说&#xff0c;那浪费的资源就不是一点点了。因此在设置cookie时&#xff0c;对它的作用域一定要设置…