回顾:Redux: 类似于 Vuex

概念:store/reducer/action

action:动作 {type,.....} 一定要有type 其他属性不做限制

reducer:通过计算产生state

公式:(state,action)=>newState

store: 容器

getState() 获取所有状态

dispatch(action) dispatch里面可以跟对象和函数, —— 函数需要单独处理——中间件

subscribe(监听函数);—— watch

触发条件:

1、dispatch ---> reducer

2、必须产生一个新的状态 newState

exp1:

1.ction.js
export const PLUS = Symbol("PLUS");
export const MINUS = Symbol("MINUS"); export function plusAction(){
return {type:PLUS};
}
export function minusAction(){
return {type:MINUS};
} 2.reducer.js import {PLUS} from "./actions"
//数据初始化
const initState = {count:1}; //创建reducer
const reducer = (state = initState,action = {})=>{
const {type} = action;
switch(type){
case PLUS:
return {...state,count:state.count+1};
default:
return state;
}
}
export default reducer; 3.store //引入
import {createStore} from "redux";
import reducer from "./reducer";
//创建store
const store = createStore(reducer);
store.subscribe(()=>console.log(store.getState()));
export default store; 4.App.js import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div className="App">
App
</div>
);
}
}
export default App; 5.Counter.js //引入
import React,{Component} from "react";
import {bindActionCreators} from "redux";
import {connect} from "react-redux";
import {plusAction,minusAction} from "./actions"; //创建组件
class Counter extends Component{
render(){
console.log(11111,this.props);
const {count,plusAction} = this.props; return (
<div>
{count}
<input onClick={plusAction} value="+" type="button"/>
</div>
);
}
} const mapStateToProps = state =>({
count:state.count
}); function mapDispatchToProps(dispatch){
return bindActionCreators({plusAction,minusAction},dispatch);
} export default connect(mapStateToProps,mapDispatchToProps)(Counter);
react-redux: {Provider,connect}

Provider:提供 作用: 把状态 store共享给所有的子组件 包在

connect 用法: connect()(Comp); ---> this.props --> {dispatch}

connect(mapStateToProps,xxxxxxx)(Comp); ---> this.props -->{ state, dispatch }

exp1:

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux"; import store from "./Counter/store";
import App from "./Counter/App";
import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')); registerServiceWorker();

异步action —— 在原有的异步函数内 包个函数—— 函数会有一个dispatch参数

在action里面有延迟操作!定时器、数据交互(ajax,fetch...)

用redux-thunk
第一步:

1、安装 cnpm i -S redux-thunk

2、引入 import thunk from "redux-thunk";

3、redux中引入applyMiddleware

import {createStore,applyMiddleware} from "redux";

4、const store = createStore(reducer,applyMiddleware(thunk));

第二步:

++在异步anctions中使用++

问题1:

++定时器++

function plusAsyncAction(){
setTimeout(()=>{
return {type:"PLUS"};
},1000);
}

通过中间件来解决

function plusAsyncAction(){
return function(dispatch){
setTimeout(()=>{
//自己手动派发action
dispatch({type:"PLUS"});
},1000);
}
}

exp1:

import {createStore,applyMiddleware} from "redux";引入模块

const store = createStore(reducer,applyMiddleware(thunk)); 使用模块

import React,{Component} from "react";
import {createStore,applyMiddleware} from "redux";
import thunk from "redux-thunk"; //创建store
//数据初始化
const initState = {count:1}; //创建reducer
const reducer = (state=initState,action={})=>{
const {type} = action;
switch(type){
case "PLUS":
return {...state,count:state.count+1};
default:
return state;
}
} //创建store
const store = createStore(reducer,applyMiddleware(thunk)); function plusAction(){
return {type:"PLUS"};
} function plusAsyncAction(){
return function(dispatch,getState){
const val = getState();//获取是修改之前的状态
console.log(val,getState);
setTimeout(()=>{
//dispatch({type:"PLUS"});
dispatch(plusAction());
},1000)
}
} class Counter extends Component{ constructor(...args){
super(...args);
store.subscribe(()=>{
console.log(store.getState());
this.forceUpdate();
});
} plus(){
store.dispatch(plusAsyncAction());
}
render(){
return (
<div>
{store.getState().count}
<input onClick={this.plus.bind(this)} value="+" type="button"/>
</div>
);
}
}
export default Counter;

res:

延迟一秒显示


问题2:

++交互(数据交互(ajax,fetch...))++

function fetchAsyncAction(){

		fetch(url).then.then(data=>{

			return {type:"GET",payload:data};

		})

		//return undefined
}

通过中间件来解决

function fetchAsyncAction(){

		return function(dispatch){
fetch(url).then.then(data=>{
dispatch({type:"GET",payload:data});
})
}
}

exp2:

数据交互

import React,{Component} from "react";
import {createStore,applyMiddleware} from "redux";
import thunk from "redux-thunk";
const url = "http://localhost:9000/api/v2/movie/in_theaters?city=北京";
//创建store
//数据初始化
const initState = {subjects:[]};
//创建reducer
const reducer = (state = initState,action = {})=>{
const {type} = action;
switch(type){
case "GET":
return {...state,subjects:action.payload};
default:
return state;
}
}
//创建store
const store = createStore(reducer,applyMiddleware(thunk)); function fetchSyncAction(){
return function(dispatch){
fetch(url).then(res=>res.json()).then(data=>{
console.log(data.subjects);
dispatch({type:"GET",payload:data.subjects});
})
}
} //创建组件
class Fetch extends Component{
constructor(...args){
super(...args);
store.subscribe(()=>{
console.log(store.getState());
this.forceUpdate();
})
}
asyncFecth(){
store.dispatch(fetchSyncAction());
}
fn(){ //url:"http://api.douban.com/v2/movie/in_theaters?city=北京",
//url:"http://localhost:9000/api/v2/movie/in_theaters?city=北京", //store.dispatch(plusAsyncAction());
fetch(url).then(res=>res.json()).then(data=>{
console.log(data.subjects); store.dispatch({type:"GET",payload:data.subjects});
})
} render(){
return (
<div>
{
store.getState().subjects.map(({id,title})=>{
return <div key={id}>{title}</div>;
})
}
<input onClick={this.fn.bind(this)} value="普通fetch" type="button"/>
<input onClick={this.asyncFecth.bind(this)} value="asyncFecth" type="button"/>
</div>
);
} } export default Fetch;

res:

        dispatch(action)
View -------------------> reducer ---------> newState 异步 同步
dispatch(asyncAction) dispatch(action)
View ----------------------> middleware拦截 ---------------> reducer --------> newState

属性验证:

安装:cnpm i -D prop-types

参考:https://reactjs.org/docs/typechecking-with-proptypes.html?#___gatsby

Test.propTypes = {
属性:验证规则
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol, }

exp1:

import React, { Component } from "react";
import PropTypes from "prop-types"; class Test extends Component {
//判断name是否是字符串,若不是字符串则报错
//,isRequired表示空也判断
//写法二
static propTypes = {
name: PropTypes.string.isRequired,
} render() {
const {name} = this.props;
return (
<div>属性验证:name: {name}</div>
);
}
}
//写法一
/*Test.propTypes = {
name: PropTypes.string.isRequired,
}*/ export default Test;

res:

符合判定不返回任何值,不符合则会报错,并提醒输入的是何种类型数据.

exp2:

自定义属性验证

import React, { Component } from "react";
// import PropTypes from "prop-types"; function Test(props){
return (
<div>属性验证:name: {props.name}</div>
);
} const PropTypes = {
string:function(props, propName, componentName){
if(typeof props[propName] !== "string"){
return new Error(`你输入的${propName}我期望的是 字符串 ,但是你给我的是 ${typeof props[propName]} `);
} }
} Test.propTypes = {
name:PropTypes.string,
}
export default Test;

res:

在异步anctions中使用的案例
豆瓣网:

代码:

1.App.js

import React, { Component } from "react";
import { Provider} from "react-redux";
import store from "./store";
import MoveBox from "./MoveBox";
import "./index.css";
let arr = [
{id:1,city:"北京"},
{id:2,city:"上海"},
{id:3,city:"深圳"},
{id:4,city:"青岛"}
]; class App extends Component {
render() {
return (
<Provider store={store}>
<div className="App">
<MoveBox arr={arr}/>
</div>
</Provider>
);
}
}
export default App;
-----------------------------------
2.index.css .active{background:pink;}
-----------------------------------
3.reducer.js import {QUERY} from "./actions" const initState = {
id:1,
city:"北京"
}; export default (state = initState,action = {})=>{
switch(action.type){
case QUERY:
return {...state,id:action.payload.id,city:action.payload.city};
default:
return state;
} };
------------------------------- 4.store.js
import {createStore, applyMiddleware} from "redux";
import thunk from "redux-thunk";
import reducer from "./reducer";
const store = createStore(reducer,applyMiddleware(thunk)); //测试用
store.subscribe(()=>{
console.log("store:",store.getState())
}); export default store;
----------------------------------
5.action.js export const QUERY = Symbol("QUERY"); ------------------------------------
6.MoveBox.js
import React, { Component } from "react";
import { connect } from "react-redux";
import MoveTitle from "./MoveTitle";
import MoveList from "./MoveList"; //url:"http://api.douban.com/v2/movie/in_theaters?city=北京",
//url:"http://localhost:9000/api/v2/movie/in_theaters?city=北京",
class MoveBox extends Component {
render() {
console.log("this.props:",this.props);
const {id,city,arr} = this.props;
return (
<div>
<MoveTitle id={id} arr={arr}/>
<MoveList city={city} />
</div>
);
}
} function mapStateToProps(state){
return {id:state.id,city:state.city};
} export default connect(mapStateToProps)(MoveBox);
-------------------------------------------
7.MoveTitle.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { QUERY } from "./actions";
class MoveTitle extends Component { fn(item){
this.props.dispatch({type:QUERY,payload:item});
} render() {
const {id,arr} = this.props;
return (
<ul>
{
arr.map(item=>{
return <input onClick={this.fn.bind(this,item)} className={item.id === id?"active":""} key={item.id} type="button" value={item.city}/>
})
} </ul>
);
}
} export default connect()(MoveTitle); --------------------------------------
8.MoveList.js
import React, { Component } from "react"; //http://localhost:9000/api/v2/movie/in_theaters?city=北京", const url = "http://localhost:9000/api/v2/movie/in_theaters?city="; class MoveList extends Component { state = {title:this.props.city,subjects:[]}; UNSAFE_componentWillReceiveProps(props){ console.log("UNSAFE_componentWillReceiveProps",props,this.props);
this.featcData(props.city);
}
componentDidMount(){
this.featcData();
} featcData(city){
city = city||this.props.city
fetch(`${url}${city}`).then(res=>res.json()).then(data=>{
console.log(111,data);
this.setState(data);
});
}
render() {
return (
<div>
{this.state.title}
<hr />
<ul>
{
this.state.subjects.map(item=>{
return <li key={item.id}>{item.title}</li>
})
}
</ul> </div>
);
}
} export default MoveList;

res:

25.redux回顾,redux中的action函数异步的更多相关文章

  1. 一个Time TodoList实例了解redux在wepy中的使用

    @subject: wepy-redux-time-todo @author: leinov @date:2018-10-30 @notice: 小程序(wepy)开发群110647537 欢迎加入 ...

  2. 记一次修改框架源码的经历,修改redux使得redux 可以一次处理多个action,并且只发出一次订阅消息

    redux是一个数据状态管理的js框架,redux把行为抽象成一个对象,把状态抽象成一个很大的数据结构,每次用户或者其他什么方式需要改变页面都可以理解成对数据状态的改变,根据出发这次改变的不同从而有各 ...

  3. 手把手教你撸一套Redux(Redux源码解读)

    Redux 版本:3.7.2 Redux 是 JavaScript 状态容器,提供可预测化的状态管理. 说白了Redux就是一个数据存储工具,所以数据基础模型有get方法,set方法以及数据改变后通知 ...

  4. LoadRunner中的Web 函数列表

    LoadRunner中的Web 函数列表 web test LoadRunner fuction_list D:\Program Files (x86)\Mercury Interactive\Mer ...

  5. (转)笔记320 SQLSERVER中的加密函数 2013-7-11

    1 --SQLSERVER中的加密函数 2013-7-11 2 ENCRYPTBYASYMKEY() --非对称密钥 3 ENCRYPTBYCERT() --证书加密 4 ENCRYPTBYKEY() ...

  6. JavaScript中的普通函数与构造函数比较

    问题 什么是构造函数?构造函数与普通函数区别是什么?用new关键字的时候到底做了什么?构造函数有返回值怎么办?构造函数能当普通函数调用吗? thisthis永远指向当前正在被执行的函数或方法的owne ...

  7. JSF页面中使用js函数回调后台bean方法并获取返回值的方法

    由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的, ...

  8. 简单理解ECMAScript2015中的箭头函数新特性

    箭头函数(Arrow functions),是ECMAScript2015中新加的特性,它的产生,主要有以下两个原因:一是使得函数表达式(匿名函数)有更简洁的语法,二是它拥有词法作用域的this值,也 ...

  9. Qt调用dll中的功能函数

    声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll),C版接口的.并且用我前两篇有关DLL文章里面的方法,从dll中导出了导入库(.lib)文件,dll中有两个函数,原型如下:   ...

随机推荐

  1. postman6 在Linux中,body和response字体显示不正常的解决方法

    在Linux中,postman的body和response使用的默认字体如果没有安装的话,会导致字体和光标的位置不一致,例如字体显示长度只有30,而光标在70的位置,导致编辑困难. 经查找css的定义 ...

  2. 每位 Ubuntu 18.04 用户都应该知道的快捷键 | Linux 中国

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/82879369 wx_fmt=jpeg& ...

  3. MySQL导出TSV格式文件

    可以使用mysqldump, 也可以使用mysql -e 使用mysqldump 因为要使用到 -T / --tab 参数, 需要先查看mysql设置的secure_file_priv mysql&g ...

  4. Effective Java 第三版——72. 赞成使用标准异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  5. SNF软件开发机器人-子系统-表单-表单设计

    表单设计 在我们做程序时总要对表单的内容进行设计,然而对控件位置等信息的调整总是麻烦的,还常常容易出错.SNF软件机器人完美的解决了这个问题. 1.效果展示: 2.使用说明: (1)打开页面,选中开发 ...

  6. CSS 水平居中与垂直居中

    前言 在CSS布局中,水平居中与垂直居中一直是用到比较多的,在本篇中将介绍水平居中.垂直居中的几种方式. 示例 HTML: <div class="parent"> & ...

  7. golang:iconv

    最近在做邮件解析的工作,遇到需要转字符集编码的情况,go官方好像没有提供这样的库,于是从github上找了一下. https://github.com/qiniu/iconv 开发环境: linux ...

  8. 2018铁三测评题write以及一些想送给你们的话

    一..前言 此文献给实验室的萌新们,以及刚刚接触CTF的同学们,希望能对你们的成长起到一些帮助. 二.关于CTF 可能你已经接触过CTF或者对它有所了解,这里我再简单介绍一下. 1.什么是CTF? C ...

  9. power designer 16.5 使用总结[转]

    测试环境:power designer 16.5.vs2010.win7 对于破解版的power designer经常出现崩溃.停止工作的情况 请运行pdlegacyshell16.exe,不要运行P ...

  10. 通过inotify实现反调试

    1.inotify linux下inotify可以实现监控文件系统事件(打开,读写删除等),inotify最常见的api有以下几个: inotify_init:用于创建一个 inotify 实例的系统 ...