25.redux回顾,redux中的action函数异步

25.redux回顾,redux中的action函数异步

回顾: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 (
      
App
); } } 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 (
{count}
); } } 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(
    
        
    ,
    document.getElementById('root'));

registerServiceWorker();

25.redux回顾,redux中的action函数异步_第1张图片

异步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 (
            
{store.getState().count}
); } } export default Counter;

res:
延迟一秒显示
25.redux回顾,redux中的action函数异步_第2张图片


问题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 (
            
{ store.getState().subjects.map(({id,title})=>{ return
{title}
; }) }
); } } export default Fetch;

res:
image

        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 (
      
属性验证:name: {name}
); } } //写法一 /*Test.propTypes = { name: PropTypes.string.isRequired, }*/ export default Test;

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

image

exp2:
自定义属性验证

import React, { Component } from "react";
// import PropTypes from "prop-types";

function Test(props){
    return (
      
属性验证:name: {props.name}
); } 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:
25.redux回顾,redux中的action函数异步_第3张图片

在异步anctions中使用的案例

豆瓣网:

25.redux回顾,redux中的action函数异步_第4张图片

代码:

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 (
      
        
); } } 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 (
); } } 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 (
    { arr.map(item=>{ return }) }
); } } 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 (
{this.state.title}
    { this.state.subjects.map(item=>{ return
  • {item.title}
  • }) }
); } } export default MoveList;

res:
25.redux回顾,redux中的action函数异步_第5张图片

posted @ 2018-08-14 21:27 飞刀还问情 阅读(...) 评论(...) 编辑 收藏

你可能感兴趣的:(nodeJs,redux)