点击上方 前端瓶子君,关注公众号

回复算法,加入前端编程面试算法每日一题群

来源:北孤清茶

https://juejin.cn/post/6953866924065292318

首先第一步利用脚手架创建一个项目,命令是:create-react-app my_redux

接着安装redux,命令:npm install \--save redux react-redux redux-thunk

Redux有三大原则

单一数据源

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

State 是只读的

唯一改变 state 的方法就是触发 actionaction 是一个用于描述已发生事件的普通对象。

使用纯函数来执行修改

为了描述 action 如何改变 state tree ,我们需要编写 reducer

接下来我们删除src下多余文件,只留下app.jsindex.js,创建store文件夹,并创建我们需要的js文件,此时src目录下应该是这些文件

|-- src
|  |-- store
|  |  |-- index.js
|  |  |-- reducer.js
|  |  |-- action.js
|  |-- index.js
|  |-- app.js
复制代码

以todoList为例

使用 action 来描述所有变化带来的好处是可以清晰地知道应用中到底发生了什么。如果一些东西改变了,就可以知道为什么变。action 就像是描述发生了什么的指示器。
action.js

//把需要操作的方法导出去
export const addTodo = (data) => {return dispatch => {//告诉reducer类型,reducer根据不同的类型做不同的操作dispatch({ type: 'ADD_TODO', data })}
}
export const delTodo = (index) => {return dispatch => {dispatch({type : 'DEL_TODO',index})}
}
复制代码

reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。刚开始你可以只有一个 reducer,随着应用变大,你可以把它拆成多个小的 reducers,分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务。
reduce.js

//创建唯一的初始化state,如果初始化元素比较多可以单独创建state.js方便管理
const initState = {todoList : ['早上五点钟起床','锻炼身体一小时','做饭吃饭']
}//编写reducer根据不同的类型做不同的操作修改state
const reducer = (state = initState,action) =>{//state是只读,所以每次修改都返回一个新的statelet newState = JSON.parse(JSON.stringify(state))switch(action.type){case 'ADD_TODO':newState.todoList.push(action.data);return newState;case 'DEL_TODO':newState.todoList.splice(action.index,1);return newState;default:return newState;}
}export default reducer
复制代码

创建store实例
store \-> index.js

// applyMiddleware: redux通过该函数来使用中间件
// createStore: 用于创建store实例
import {createStore,applyMiddleware} from 'redux'
//thunk中间件可以支持异步action
import thunk from 'redux-thunk'
import reducer from './reducer'
const store = createStore(reducer,applyMiddleware(thunk))
export default store
复制代码

至此,我们已经完成了所有使用Redux的准备工作,接下来就在React组件中使用Redux
首先编写入口文件index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';引入创建好的store实例
import store from './store'
// Provider是react-redux两个核心工具之一,作用:将store传递到每个项目中的组件中
import {Provider} from 'react-redux'ReactDOM.render(<Provider store={store}>{/* 将store作为prop传入,即可使应用中的所有组件使用store */}<App /></Provider>,document.getElementById('root')
);
复制代码

最后app.js

import React, { Component } from 'react'
// connect方法的作用:将额外的props传递给组件,并返回新的组件,组件在该过程中不会受到影响
import { connect } from 'react-redux'
// 引入action
import {addTodo,delTodo} from './store/action'
class App extends Component {state = {value : ''}changeValue = (e) =>{this.setState({value : e.target.value,})}addTodoFn = () =>{//触发addTodo添加备忘的actionthis.props.addTodo(this.state.value)this.setState({value :''})}delTodoFn = (index) =>{//触发delTodo删除备忘的actionthis.props.delTodo(index)}render() {return (<div><ol>{this.props.todoList.map((item,index)=>(<li key={index} onClick={this.delTodoFn.bind(this,index)}>{item}</li>))}</ol><input type="text" value={this.state.value} onChange={this.changeValue}/><button onClick={this.addTodoFn}>添加</button></div>)}
}
// mapStateToProps:将state映射到组件的props中
const mapStateToProps = (state) => ({todoList : state.todoList
})
// mapDispatchToProps:将action里的dispatch映射到组件的props中
const mapDispatchToProps = {addTodo,delTodo
}export default connect(mapStateToProps, mapDispatchToProps)(App)复制代码

@connect装饰器

装饰器可以让代码写起来更顺手,看起来也简洁一点,

  1. 在命令行执行命令 `npm run eject`。如果报错的信息大概意思是:有些文件未被追踪到,那么直接`git add .` 再 `git commit -m`"",或者直接在`.gitignore`中忽略这些文件\(不建议\);
    
  2. 之后`package.json`中会出现很多依赖建议`yarn/npm i` 一下,防止网速不好出现丢包现象;
    
  3. 然后打开`package.json`文件,找到`"babel"`开头的一个对象,\(一般在最后,\),这是原始的样子:
    
"babel": {"presets": ["react-app"]}
复制代码

加入另外一项:

"babel": {"presets": ["react-app"],"plugins": [["@babel/plugin-proposal-decorators",{"legacy": true}]]}
复制代码

最后重启项目就可以了,一定要重启项目不然可能会报错Support for the experimental syntax 'decorators-legacy' isn't currently enabled (6:1):
然后就可以使用@conncet装饰器了,把app.js可以修改如下:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import {addTodo,delTodo} from './store/action'
//直接在class上一行,接收两个参数,跟之前的写法差不多,第一个参数是需要用的state,第二个参数是需要用的action
@connect(state=>({todoList : state.todoList
}),{addTodo,delTodo})
class App extends Component {state = {value : ''}changeValue = (e) =>{this.setState({value : e.target.value,})}addTodoFn = () =>{//触发addTodo添加备忘的actionthis.props.addTodo(this.state.value)this.setState({value :''})}delTodoFn = (index) =>{//触发delTodo删除备忘的actionthis.props.delTodo(index)}render() {return (<div><ol>{this.props.todoList.map((item,index)=>(<li key={index} onClick={this.delTodoFn.bind(this,index)}>{item}</li>))}</ol><input type="text" value={this.state.value} onChange={this.changeValue}/><button onClick={this.addTodoFn}>添加</button></div>)}
}
//用@connect装饰器一定要以这种方式导出,不然报错,具体什么原因我还没找到
export default App复制代码

调试工具插件

window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
在redux中添加这个插件是在chrome浏览器可以看到state的每一步流程,更加清晰,在store下index.js中添加修改

import {createStore,applyMiddleware,compose} from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducer'
const composeEnhancers =typeof window === 'object' &&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...}) : compose;const enhancer = composeEnhancers(applyMiddleware(thunk),// other store enhancers if any
);
const store = createStore(reducer, enhancer);
export default store
复制代码


最后

欢迎关注【前端瓶子君】✿✿ヽ(°▽°)ノ✿

回复「算法」,加入前端编程源码算法群,每日一道面试题(工作日),第二天瓶子君都会很认真的解答哟!

回复「交流」,吹吹水、聊聊技术、吐吐槽!

回复「阅读」,每日刷刷高质量好文!

如果这篇文章对你有帮助,「在看」是最大的支持

》》面试官也在看的算法资料《《

“在看和转发”就是最大的支持

入门 redux 和 @connect 装饰器相关推荐

  1. ant design pro 页面加载原理及过程,@connect 装饰器

    一.概述 以列表页中的标准列表为主 Ant Design Pro 默认通过只需浏览器单方面就可处理的 HashHistory 来完成路由.如果要切换为 BrowserHistory,那在 src/in ...

  2. Angular2入门:TypeScript的装饰器

    Angular2入门:TypeScript的装饰器 转载于:https://www.cnblogs.com/lexiaofei/p/9215505.html

  3. redux VS mobx (装饰器配合使用)

    前言:redux和mobx都是状态管理器,避免父级到子级再到子子级嵌套单向数据流,可以逻辑清晰的管理更新共享数据.(刷新页面redux储蓄数据即消失) 配置使用装饰器(使用高阶函数包装你的组件): n ...

  4. python进展_Python3的介绍和进展-“filter()”“time()”和decorator。,入门,与,进阶,filtertime,装饰,器...

    一:filter() 依次把iterable里的元素扔进function中,最后"过滤"出来的是在function里表现为"真"的元素. 特性:1:functi ...

  5. python中修饰器的优点和作用_Python入门基础教程之装饰器

    Python装饰器的定义:在代码运行期间在不改变原函数定义的基础上,动态给该函数增加功能的方式称之为装饰器(Decorator) 装饰器的优点和用途: 1. 抽离出大量函数中与函数功能本身无关的的雷同 ...

  6. Python 学习入门(26)—— 装饰器

    装饰函数和方法 我们先定义两个简单的数学函数,一个用来计算平方和,一个用来计算平方差: # get square sum def square_sum(a, b):return a**2 + b**2 ...

  7. 人人都能看懂的 Python 装饰器入门教程

    大家好,我是萱萱! 之前的文章中提到,很多人认为理解了装饰器的概念和用法后,会觉得自己的 Python 水平有一个明显的提高. 但很多教程在一上来就会给出装饰器的定义以及基本用法,例如你一定会在很多文 ...

  8. python 装饰器入门

    1. 装饰器入门 1.1. 需求是怎么来的? 装饰器的定义很是抽象,我们来看一个小例子. ? 1 2 3 4 def foo():     print 'in foo()'    foo() 这是一个 ...

  9. python入门之装饰器

    入门原理: 一系列函数要做相同的修改,在这些函数执行之前做的操作,或者在执行之后做的操作都可以在一个装饰器(函数)里修改 作用: 在不改变原函数的情况下,对原函数的操作前或者操作后做些改变,这就是装饰 ...

最新文章

  1. 四、Input框改placeholder中字体的颜色
  2. python朋友圈为什么这么火-用Python发一个高逼格的朋友圈「附代码」
  3. Effective C# Item45 : 优先选择强异常安全保证
  4. 【建议收藏】数学建模竞赛网站汇总
  5. php 加入日志功能,php怎么写一个日志功能的函数
  6. Linux kill 杀死指定进程
  7. UI界面排版搞不定 ?看看这些优秀的实例模板,可临摹学习!
  8. Linux(1) 目录结构
  9. LeetCode 415. 字符串相加 (逢十进一模版字符处理)
  10. JavaScript基础知识。
  11. 原来查询语句还有这功能,累计变量值
  12. php 翻译接口,翻译接口整理
  13. 中科方德桌面操作系统_国产操作系统——中科方德桌面操作系统,USB无线网卡配置...
  14. python实现整数反转
  15. PICTURE writeup By K龙
  16. TCPC 可用于笔记本,平板等HOST端的解决方案
  17. 在VS中如何设置自动换行
  18. 知识图谱问答 | (3) 关系分类概述
  19. BilSTM 实体识别_肿瘤新抗原(neoantigen)专题八:新抗原识别策略使难治性实体瘤的个体化免疫治疗成为可能...
  20. 如何批量将 Word 文档转为 ePub 格式

热门文章

  1. 《认知天性》这本书对我的启发,以及我在日常中的应用
  2. Revit二次开发之双事件:空闲事件与DocumentChanged事件
  3. 大数据周周看:百分点集团全资并购极速洞察,精准医疗创企“海普洛斯”获2.1亿元融资
  4. windows安装nginx莫名其妙 CreateFile()权限不够创建问题
  5. day03--java基础编程:面向对象,构造方法,代码块讲解,this super,static,final,访问修饰符,方法重写,向上/下造型,main方法,抽象类,接口,设计模式,异常,内部类
  6. html 完整性验证,验证消息完整性的方法是() - 问答库
  7. 数仓建模之声明粒度 一文读懂什么是粒度 看完保证通透!
  8. Socket TCP协议解决粘包、半包问题的三种解决方案
  9. 删除的监控视频怎么恢复?用数据恢复软件解决
  10. 联想服务器x3250 m5文档,【联想x3250 M5参数】联想x3250 M5系列服务器参数-ZOL中关村在线...