2019-09-13 11:48:31 weixin_42295194 阅读数 50
  • Cordova+React+OnsenUI+Redux新闻App开发实战教程

    Cordova+React+OnsenUI+Redux新闻App开发实战视频培训课程以真实的案例讲解Cordova开发的流程设计,React+Redux的架构理念设计新闻App的数据流管理,整体的技术栈包括混合应用技术架构、cordova平台实战(视频教程)、webpack的实战、redux+middleware数据流管理、onsenui的整合应用,针对ios + android平台程序混淆压缩编译并打包终的产品。

    1750 人正在学习 去看看 姜博

React 16 学习笔记(一)使用 Redux react-redux TodoList

使用create-react-app创建React项目

在指定目录使用如下命令创建项目todolist

 create-react-app todolist

安装redux

yarn add redux

在这里插入图片描述
安装react-redux

yarn add react-redux

在这里插入图片描述

修改目录

剔除不需要的文件如图:

在这里插入图片描述

创建存储store

创建一个store目录,store中创建两个文件index,js和reducer.js
reducer.js

const defaultState={
  inputValue:'',
  list:[]
};

export default (state=defaultState, action) => {
    return state
}

index.js

import { createStore } from "redux";
import reducer from "./reducer";

const store = createStore(reducer);

export default store;

修改index.js

Provider 功能是使被 包裹的TodoList组件使用react-redux

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import TodoList from './TodoList';
import store from './store'

const App = (
    <Provider store={store}>
        <TodoList/>
    </Provider>
);

ReactDOM.render(<App />, document.getElementById('root'));



创建TodoList.js

class TodoList extends Component{
    render() {
        return (
            <Fragment>
                <input />
                <button>提交</button>
            </Fragment>
        )
    }
}

const mapStateToProps = (state)=>{
    return {
        inputValue: state.inputValue,
        list:state.list,
    }
};

const mapDispatchToProps=(dispatch)=>{
    return {
        
    }
};

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

修改input框value属性

input 值定义为inputValue,onChang事件,绑定一个InputChange方法

<input value={inputValue} onChange={this.props.InputChange}/>

在mapDispatchToProps中构造InputChange方法

这里需要定义一个type,用于区别传递的是哪个方法的action,通过 dispatch(action);直接将action传递给reducer

const mapDispatchToProps=(dispatch)=>{
    return {
        handleInputChange(e) {
            const action = {
                type:'CHANGE_INPUT_VALUE',
                value:e.target.value
            };
            dispatch(action);
        },

    }
};

reducer接受传送过来的action

reducer不能直接修改store,因此需要先深拷贝一份store中的state,newState 中的inputValue修改后,将newState返回给store,store自动修改自己的数据
reducer.js

export default (state = defaultState, action) => {
    if (action.type === 'CHANGE_INPUT_VALUE') {
        const newState = JSON.parse(JSON.stringify(state)); // 拷贝一份
        newState.inputValue = action.value;
        return newState;
    }
    return state
}

输入的数据存入list,并显示

将上一步骤已修改的inputValue值,通过点击按钮,添加到list中。list通过map()方法循环显示在页面上

为按钮点击事件绑定方法

<button onClick={this.props.handleClick}>提交</button>

在mapDispatchToProps中构造handleClick方法

这里只需要传递一个type给reducer就可以了,不需要再讲inputValue进行传递,因为上步骤中已经修改好store中inputValue的值,直接使用就可以

handleClick(){
            const action={
                type: 'CLICK_BUTTON',
            };
            dispatch(action);
        },

reducer接受传送过来的action

if (action.type === 'CLICK_BUTTON') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.push(newState.inputValue);
        newState.inputValue = '';//起到清空页面input框输入值
        return newState;
    }

页面显示list中的数据

map需要一个key值,使用index;

{
                    this.props.list.map((item,index)=>{
                        return (
                            <li key={index} >{item}</li>
                        )
                    })
                }

添加点击删除功能

删除list中的某个值,需要知道这个值所对应的下标,需要将index传递给一个方法。bind()可以向方法传递参数,但是参数不能是第一个位置。,为li标签绑定一个点击事件,通过bind()给方法传递index参数
li标签绑定事件方法

<li key={index} onClick={deleteItem.bind(this,index)}>{item}</li>

在mapDispatchToProps中构造deleteItem方法

deleteItem(index){
            const action={
                type:'DELETE_ITEM',
                index
            };
            dispatch(action);
        },

reducer接受传送过来的action

splice删除对应index的list元素

if (action.type === 'DELETE_ITEM') {
        const newState = JSON.parse(JSON.stringify(state));
        newState.list.splice(action.index,1);
        return newState;
    }

代码优化

优化主要在两个方面:
一、todolist组件中不含有复杂逻辑,只有一个render()函数,改写为UI组件
二、ActionTypes进行拆分
首先拆分ActionTypes,创建actionTypes.js,需要对TodoList.js 和reducer.js进行修改

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const CLICK_BUTTON = 'click_button';
export const DELETE_ITEM = 'delete_item';

TodoIist.js

import React,{ Fragment } from 'react';
import { connect } from 'react-redux';
import {CHANGE_INPUT_VALUE,CLICK_BUTTON,DELETE_ITEM} from './store/actionTypes'

const TodoList= (props)=>{
    const {inputValue,handleInputChange,handleClick,list,deleteItem} = props;
    return (
        <Fragment>
            <input value={inputValue} onChange={handleInputChange}/>
            <button onClick={handleClick}>提交</button>
            {
                list.map((item,index)=>{
                    return (
                        <li key={index} onClick={deleteItem.bind(this,index)}>{item}</li>
                    )
                })
            }
        </Fragment>
    )
};

const mapStateToProps = (state)=>{
    return {
        inputValue: state.inputValue,
        list:state.list,
    }
};

const mapDispatchToProps=(dispatch)=>{
    return {
        handleInputChange(e) {
            const action = {
                type:CHANGE_INPUT_VALUE,
                value:e.target.value
            };
            dispatch(action);
        },
        handleClick(){
            const action={
                type: CLICK_BUTTON,
            };
            dispatch(action);
        },
        deleteItem(index){
            const action={
                type:DELETE_ITEM,
                index
            };
            dispatch(action);
        },
    }
};

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);

总结

到此完成了全部代码,Redux需要注意:reducer不能直接修改store中的数据,需要先深拷贝,修改,再返回给store,同时reducer必须是一个纯函数,源代码

2019-01-11 10:35:18 weixin_40614372 阅读数 608
  • Cordova+React+OnsenUI+Redux新闻App开发实战教程

    Cordova+React+OnsenUI+Redux新闻App开发实战视频培训课程以真实的案例讲解Cordova开发的流程设计,React+Redux的架构理念设计新闻App的数据流管理,整体的技术栈包括混合应用技术架构、cordova平台实战(视频教程)、webpack的实战、redux+middleware数据流管理、onsenui的整合应用,针对ios + android平台程序混淆压缩编译并打包终的产品。

    1750 人正在学习 去看看 姜博

注意:未经允许不可私自转载,违者必究

React Native官方文档:https://reactnative.cn/docs/getting-started/

redux官方文档:https://www.redux.org.cn/

项目地址GitHub地址:https://github.com/zhouwei1994/nativeCase.git

安装redux react-redux  react-navigation-redux-helpers

在项目目录下cmd里面运行以下命令:

yarn add redux

yarn add react-redux

yarn add react-navigation-redux-helpers

没有安装yarn镜像的请看教程:https://blog.csdn.net/weixin_40614372/article/details/86154119

redux react-redux  react-navigation-redux-helpers在React Native里面的配置

查看项目目录:https://github.com/zhouwei1994/nativeCase/blob/master/README.md

本项目是用react-navigation来做路由,路由长度需要由redux来托管,所以下面代码会和react-navigation关联,没有配置react-navigation请参考这篇文字https://blog.csdn.net/weixin_40614372/article/details/86237863

在src/store文件下创建:

  1. index.js    redux配置
  2. stores.js   redux数据中心

index.js文件如下:


import AppNavigator from './../router/index';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { AsyncStorage } from 'react-native';
import { reduxifyNavigator, createReactNavigationReduxMiddleware, createNavigationReducer } from 'react-navigation-redux-helpers';
import { connect } from 'react-redux';
import { stores,cacheNameList } from './stores';
//创建导航状态数据商店redux
const navReducer = createNavigationReducer(AppNavigator);
//结合redux
const appReducer = combineReducers({
    ...stores,
    nav: navReducer
});
// 创建React Navigation Redux中间件
const middleware = createReactNavigationReduxMiddleware(
    "Root",
    state => state.nav,
);
// 生成reduxify导航组件
const App = reduxifyNavigator(AppNavigator, "Root");
const mapStateToProps = (state) => ({
    state: state.nav,
});
//创建数据商店
export const store = createStore(
    appReducer,
    applyMiddleware(middleware),
);
export const AppWithNavigationState = connect(mapStateToProps)(App);
//每次启动项目的时候自动把 cacheNameList 里面提供名称的数据填充到redux数据中心
async function setCacheData() {
    for (var item of cacheNameList) {
        let getData = await AsyncStorage.getItem(item);
        if (getData) {
            store.dispatch({
                type: item,
                data: JSON.parse(getData)
            });
        }
    }
};
setCacheData();

stores.js文件如下:

import { modifyJson } from "./../config/utils";
import { AsyncStorage } from 'react-native';
//缓存浏览器的数据名称
export const cacheNameList = ["USER_INFO_TODO", "OTHER_TODO"];
function storeStorage(key,text) {
    AsyncStorage.setItem(key, text);
}
//用户数据
function userInfo(
    state = {
        token: "fsfsfsdfsd"
    }, action) {
    switch (action.type) {
        case 'USER_INFO_TODO':
            if (action.data) {
                var userText = modifyJson(action.data,state)
                storeStorage('USER_INFO_TODO', JSON.stringify(userText));
                return userText;
            } else {
                return state;
            }
        default:
            return state
    }
};

function other(state = "123456789", action) {
    switch (action.type) {
        case "OTHER_TODO":
            if (action.data) {
                // storage.setItem('OTHER_TODO', JSON.stringify(action.data));
                return action.data;
            } else {
                return state;
            }
        default:
            return state
    }
}
export const stores = {
    userInfo,
    other,
};

在主入口文件App.js里面如下配置:

import React, { Component } from 'react';
import { ToastAndroid, BackHandler, StatusBar } from 'react-native';
import { NavigationActions } from "react-navigation";
import { Provider } from 'react-redux';
import { store, AppWithNavigationState } from './store/index';

export default class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

redux 的使用

如下代码:

import React, { Component } from 'react';
import { ScrollView, StyleSheet, Text, View, Button } from 'react-native';
import { connect } from 'react-redux';
class My extends Component {
    constructor(props) {
        super(props)
    }
    componentDidMount() {
        console.log(this.props);
    }
    render() {
        return (
            <ScrollView style={styles.myPage}>
                <Text style={{fontSize:40}}>全局状态管理方法</Text>
                <Text>token:{this.props.userInfo.token}</Text>
                <Button title="修改token" onPress={this.props.setUserInfo}></Button>
                <Text>更多数据:{this.props.other}</Text>
                <Button title="修改更多" onPress={this.props.setOther}></Button>
            </ScrollView>
        );
    }
}
let USER_INFO_TODO = {
    type: "USER_INFO_TODO",
    data: {
        token: ""
    }
};
let OTHER_TODO = {
    type: "OTHER_TODO",
    data: ""
};
//获取redux里面的数据
let mapStateToProps = function (state) {
    return {
        userInfo: state.userInfo,
        other: state.other,
    }
}
//给对应的数据赋值
let mapDispatchToProps = function (dispatch) {
    return {
        setUserInfo: () => {
            USER_INFO_TODO.data.token = "123";
            return dispatch(USER_INFO_TODO)
        },
        setOther: () => {
            OTHER_TODO.data = "456";
            return dispatch(OTHER_TODO)
        }
    }
}
//redux和页面关联
export default connect(mapStateToProps, mapDispatchToProps)(My);
const styles = StyleSheet.create({
    myPage: {
        backgroundColor: '#f5f5f5',
    },
});

这里是redux的全部实例,不知道各位小伙伴能不能看懂

项目地址GitHub地址:https://github.com/zhouwei1994/nativeCase.git

注意:未经允许不可私自转载,违者必究

 

2019-03-11 21:54:34 weixin_43618932 阅读数 24
  • Cordova+React+OnsenUI+Redux新闻App开发实战教程

    Cordova+React+OnsenUI+Redux新闻App开发实战视频培训课程以真实的案例讲解Cordova开发的流程设计,React+Redux的架构理念设计新闻App的数据流管理,整体的技术栈包括混合应用技术架构、cordova平台实战(视频教程)、webpack的实战、redux+middleware数据流管理、onsenui的整合应用,针对ios + android平台程序混淆压缩编译并打包终的产品。

    1750 人正在学习 去看看 姜博

React
reduc 是(React全家桶)的核心成员
新建项目怎么使用 redux和react-redux?

  • 新建文件夹store
    • 在 store文件夹内新建一个index.js文件
      • 在 index.js文件中我们需要引入{createStore,combineReducers,applyMiddleWare}三个函数
        • 随后安装 redux-thunk插件
        • 使用 createStore创造 store对象,
          • createStore的第一个参数是:需要我们传入 根reducer(所有 reducer.js纯函数中的更新数据的方法,是通过combineReducers产生的)
          • createStore的第二个参数是:applyMiddleWare(reduxThunk) // 一个用于使用异步操作的插件
          • 以后每新增一个reducer我们都要在这个文件里引入,然后放到combineReducers的参数中
  • 一般还会有actions.js reducers.js action-types.js 这个三个文件

index.js

import {createStore,combineReducers,applyMiddleware} from 'redux'
import reduxThunk from 'redux-thunk' // 用于使用异步操作的插件
import {colorReducer,countReducer} from './reducers.js'

let rootReducer = combineReducers({
    colorReducer,countReducer
});
let store = createStore(rootReducer,applyMiddleware(reduxThunk));

// export default {store}
// 使用方想要通过解构的方式 获取store 是不支持的
export default store

  • 在新建项目的时候
    • 一般情况下,需要我们去创造一个对应的 reducers.js纯函数文件
      • 然后把你创建的这个 reducers.js中的{colorReducer,countReducer}用来更新数据的方法, 作为 combineReducers实参,引入到 combineReducers的函数方法中。
    • 然后再去对应的添加一个actions文件

reducers.js

import * as types from './action-types.js'
// 纯函数
export function colorReducer(state,action){
    if(!state){ 
        return{
            color:'blue'
        }
    }
    switch(action.type){
        case types.COLOR:
            return{
                ...state,
                color:action.color
            }
            break;
        default:
            return state
            break;
    }
}
export function countReducer(state,action){
    if(!state){ 
        return{
            count:0
        }
    }
    switch(action.type){
        case types.COUNT:
            return{
                ...state,
                coUNT:action.count
            }
            break;
        default:
            return state
            break;
    }
}
  • 在新建项目的时候
    • 一般情况下,需要我们去创造一个对应的 actions.js文件
      • 然后把你创建的这个 actions.js中的 changeColor,changeColor11 方法是由于用户操作触发执行,从而实现数据更新。

actions.js

import {COLOR} from './action-types.js'
// import store from '../store/index.js' 
export const changeColor = (str)=>{
    return{
        type:COLOR,
        color:str
    }
}
<-- 这个函数体里面我们用来进行对异步代码的编写 -->
export const changeColor11 = (str)=>{
    return function(dispatch,getState){
        <-- 这里的 dispatch,getState就是 store 里面对应的两个函数 -->
        console.log(dispatch,getState);
        // console.log(store.getState());
        setTimeout(()=>{
            dispatch({
                type:COLOR,
                color:str
            })
        },2000);
    }
}
  • 在创建 actions.js文件的之后
    • 为了方便在有文件数据起冲突的时候可以快速更改,一般情况下,需要我们去创造一个对应的 action-types.js文件
      • 该文件存储的都是一些常量
      • 如:import {COLOR} from './action-types.js' ,在 actions.js文件中,可以用action-types.js文件中创造的属性依据 type作为属性值,来判断在函数方法中需要数据更新的属性
      • 如:import * as types from './action-types.js,在 reducers.js纯函数文件中,可以用 action-types.js文件中创造的属性依据 type作为属性值,来判断在函数方法中需要数据更新的属性

action-types.js

export const COLOR = 'CHANGE_COLOR' 
export const COUNT = 'CHANGE_COUNT' 
  • 创建完成之后,在根组件之中,我们使用 Provider(redux-react提供)组件包裹住我们的内容
    • 然后给这个组件设置一个 store行内属性
      • 行内属性 store值是:通过createStore产生的那个对象(store文件夹–>index.js)

react跟组件 index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux'
import store from '../store/index.js'
import Header from './header.js'
import Content from './content.js'
import Content2 from './content.js'

class App extends React.Component {
    constructor() {
        super();
        
    }
    render() {
        return (<Provider store={store}>
            {/* 是把 store赋值给了Provide的context,
            使其所有的子孙组件都可以从其中获取数据 */}
            <div className=''>
                <Header/>
                <Content/>
                <Content2/>
            </div>
        </Provider>)
    }
}

export default App
  • 创建子组件组件Hreder,Content
    • 对于所有的子孙组件;用this.props则可以到获取 store中的 state数据,同时需要使用connect(redux-react)处理当前组件,

Header

import React from 'react';
import ReactDOM from 'react-dom';
import {connect} from 'react-redux'
class Header extends React.Component {
    constructor() {
        super();
        
    }
    render() {
        return <div className=''>
            <h1 style={{color:this.props.color}}>头部</h1>
        </div>;
    }
}
<-- 通过 connect方法,子组件封装 -->
Header = connect((state)=>{
    return{
        color:state.colorReducer.color
    }
},(dispatch)=>{
    return{
        dispatch
    }
})(Header)

export default Header

Content

import React from 'react';
import {connect} from 'react-redux';
import {changeColor,changeColor11} from '../store/actions.js'
import store from '../store/index.js';
class Content extends React.Component {
    constructor() {
        super();
        
    }
    fn(str){
        this.props.dispatch(changeColor11(str));
    }
    render() {
        return <div className=''>
            <h2 style={{color:this.props.color}}>这是内容</h2>
            <button
                onClick={()=>{this.fn('red')}}
            >red</button>
            <button
                onClick={()=>{this.fn('yellow')}}
            >yellow</button>
        </div>;
    }
}
<-- 通过 connect方法,子组件封装 -->
Content = connect((state)=>{
    return{
        color:state.colorReducer.color,
    }    
},(dispatch)=>{
    return{
        dispatch
    }
})(Content)
export default Content

Content2.js

  • Content2.js相比起上面的 Content.js没有什么本质上的不同,只是把高阶函数 connect的第二个参数从(dispatch)=>{return{dispatch}}变为{changeColor:changeColor,changeColor11:changeColor11}这样写可以使点击事件执行触发函数方法fn,看上去更方便,然而却不利于理解。
import React from 'react';
import ReactDOM from 'react-dom';
import {connect} from 'react-redux';
import {changeColor,changeColor11} from '../store/actions.js'
import store from '../store/index.js';
class Content2 extends React.Component {
    constructor() {
        super();
        
    }
    fn(str){
        this.props.changeColor11(str);
    }
    render() {
        return <div className=''>
            <h2 style={{color:this.props.color}}>这是内容</h2>
            <button
                onClick={()=>{this.fn('red')}}
            >red</button>
            <button
                onClick={()=>{this.fn('yellow')}}
            >yellow</button>
        </div>;
    }
}
<-- 通过 connect方法,子组件封装 -->
Content2 = connect((state)=>{
    return{
        color:state.colorReducer.color,
    }    
},{
    changeColor,
    changeColor11
})(Content2)

export default Content2
2019-08-06 15:09:59 qq_35536883 阅读数 127
  • Cordova+React+OnsenUI+Redux新闻App开发实战教程

    Cordova+React+OnsenUI+Redux新闻App开发实战视频培训课程以真实的案例讲解Cordova开发的流程设计,React+Redux的架构理念设计新闻App的数据流管理,整体的技术栈包括混合应用技术架构、cordova平台实战(视频教程)、webpack的实战、redux+middleware数据流管理、onsenui的整合应用,针对ios + android平台程序混淆压缩编译并打包终的产品。

    1750 人正在学习 去看看 姜博

React Redux

React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。细节参考React Redux官方英文文档

安装

npm install react-redux
或
yarn add react-redux

Provider

<Provider / >全局使用

Connect() 连接组件和store,容器属性中使用

两个参数:mapStateToProps和mapDispatchToProps

使用mapStateToProps抽取数据(mapState)

作为connect的第一个参数,每当store state 改变时就被调用

不希望订阅store,传递null或undefined替代mapStateToProps。

接收整个store state,并返回一个组件需要的数据对象

  • 声明:function mapStateToProps(state, ownProps?)返回连接组件需要的数据的纯对象。
  1. State,整个store state对象
  2. ownProps(可选),组件需要用自身的props数据从store中检索出数据,传入ownProps。包含所有传递被connect的组件的props。
  3. 返回值,包含组件用到的数据的纯对象
    每个对象字段作为组建的props
    字段中的值用来判断组件是否需要重新渲染
  • 使用指南:使用mapStateToProps改造从store中取出的数据
  1. 使用Selector方法去抽取和转化数据
  2. mapStateToProps方法应该足够快
  3. mapStateToProps方法应该纯净且同步
  • mapStateToProps和性能
  1. 仅在需要时返回新的对象引用(浅比较)
    使用selector function,只在输入值发生改变后运行。
  2. 仅在数据改变时运行开销大的操作
    一些转化可以在action创建函数或者reducer中运算,把转化过的数据存储在store中
    转化也可以在组件的render()生命周期中完成
    若转化必须在mapStateToProps方法中完成,建议使用selector function
  • 行为与总结
  1. mapStateToProps在store state相同的情况下不会运行
  2. 声明参数的数量影响行为
    不应该增加ownProps参数,除非你实在是需要它。

使用mapDispatchToProps分发actions

  • 分发actions的路径:
  1. 默认地,一个已连接组件可以接收props.dispatch然后自己分发actions
  2. Connect能够接收mapDispatchToProps作为第二个参数
    更加声明式
    指明你的组件所实际需要分发的那些actions,把所有的action creators使用函数封装起来
    把action分发逻辑向子(未连接)组件传递
  • 两种mapDispatchToProps的形式
  1. 函数形式,更高自由度、能够访问dispatch和可选择的ownProps
  2. 对象形式,更声明式,更易于使用(建议使用)

将mapDispatchToProps定义为一个函数**

  1. 参数: dispatch、ownProps(可选)
  • 返回值:返回一个纯对象
  1. 每一个对象的字段都会作为你的组件的一个独立prop,并且字段的值通常是一个调用后能分发action的函数。
  2. 如果你在dispatch()中使用了action创建函数(区别于纯对象形式的action),通常约定字段名与action创建函数的名称相同
  • 使用bindActionCreators定义mapDispatchToProps函数
    bindActionCreators 接收两个参数:
  1. 一个函数(action creator)或一个对象(每个属性为一个action creator)
  2. Dispatch
  • 手动注入dispatch
    可以通过在mapDispatchToProps的return中添加dispatch把它重新注入你的组件

将mapDispatchToProps定义为一个对象

  1. 每个mapDispatchToProps对象的字段都被假设为一个action创建函数
  2. 你的组件不再接收dispatch作为一个prop
2018-10-11 16:48:31 xutongbao 阅读数 67
  • Cordova+React+OnsenUI+Redux新闻App开发实战教程

    Cordova+React+OnsenUI+Redux新闻App开发实战视频培训课程以真实的案例讲解Cordova开发的流程设计,React+Redux的架构理念设计新闻App的数据流管理,整体的技术栈包括混合应用技术架构、cordova平台实战(视频教程)、webpack的实战、redux+middleware数据流管理、onsenui的整合应用,针对ios + android平台程序混淆压缩编译并打包终的产品。

    1750 人正在学习 去看看 姜博

 

App.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import Header from './Header'

const themeReducer = (state, action) => {
  if (!state) return {
    themeColor: 'red'
  }
  switch (action.type) {
    case 'CHANGE_COLOR':
      return { ...state, themeColor: action.themeColor }
    default:
      return state
  }
}

const store = createStore(themeReducer)

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <Header />
      </Provider>
    );
  }
}

export default App;

Header.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import ThemeSwitch from './ThemeSwitch'

class Header extends Component {
  static propTypes = {
    themeColor: PropTypes.string
  }

  render () {
    return (
      <div>
        <h1 style={{ color: this.props.themeColor }}>xutongbao</h1>
        <ThemeSwitch/>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    themeColor: state.themeColor
  }
}
Header = connect(mapStateToProps, null)(Header)

export default Header

ThemeSwitch.js:

import React, { Component } from 'react';
import PropTypes from 'prop-types'
import { connect } from 'react-redux'

class ThemeSwitch extends Component {
  static contextTypes = {
    store: PropTypes.object
  }

  handleSwitchColor (color) {
    if (this.props.onSwitchColor) {
      this.props.onSwitchColor(color)
    }
  }

  render () {
    return (
      <div>
        <button onClick={this.handleSwitchColor.bind(this, 'red')}>Red</button>
        <button onClick={this.handleSwitchColor.bind(this, 'blue')}>Blue</button>
      </div>
    )
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onSwitchColor: (color) => {
      dispatch({ type: 'CHANGE_COLOR', themeColor: color })
    }
  }
}
ThemeSwitch = connect(null, mapDispatchToProps)(ThemeSwitch)

export default ThemeSwitch

 

 

 

 

 

react+redux+react-redux

阅读数 285

react redux react-redux

博文 来自: u013558749

redux react使用

阅读数 294

没有更多推荐了,返回首页