在react中使用redux_react,redux,和react-redux - CSDN
精华内容
参与话题
  • redux就是react生态一个很好的数据和状态管理工具,本文将介绍在react项目如何使用redux。 初始化react项目 首先需要初始化react项目,安装了nodejs环境的情况下,运行下面了命令安装create-react-app工具...

    react项目中,组件通信和状态管理是非常麻烦的,特别是在涉及到父子组件传值的时候,就需要父子传值的方法,将会特别麻烦。而redux就是react生态中一个很好的数据和状态管理工具,本文将介绍在react项目中如何使用redux

    初始化react项目

    首先需要初始化react项目,在安装了nodejs环境的情况下,运行下面了命令安装create-react-app工具。

    npm install create-react-app -g
    

    之后npm会在全局安装create-react-app工具,可以直接通过命令生成react项目,初始化命令如下。

    // 进入创建项目的目录
    create-react-app reactapp
    

    运行命令后初始化了一个叫reactapp的项目,项目中src目录就是编写代码的目录。将src下面的所有代码删除,并引入如下两个文件。

    // index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    
    ReactDOM.render(<App />, document.getElementById('root'));
    
    // App.js
    import React, { Component } from 'react';
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {  }
      }
      render() { 
        return (
          <div>hello</div>
        );
      }
    }
     
    export default App;
    

    其中index.js是项目的入口文件,而App.js是新增的一个组件。

    新建一个组件

    这里新建一个组件,使用span标签显示一个数字,使用button按钮来加数字。

    import React, { Component } from 'react';
    
    class Page extends Component {
        constructor(props) {
            super(props);
            this.state = {  }
        }
        render() { 
            return (
                <div>
                    <span>1</span>
                    <button>+</button>
                </div>
            );
        }
    }
     
    export default Page;
    

    现在页面只有样式,没有交互,之后会添加交互。

    创建redux仓库

    首先安装redux

    yarn add redux
    

    然后在项目中创建store目录,并在目录中添加index.js是文件。

    import { createStore } from 'redux';
    const store = createStore();
    export default store;
    

    创建仓库后还需要一个用于管理的模块reducer,在store目录中添加reducer.js是文件。

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

    然后在index.js中引入reducer.js是文件。

    import { createStore } from 'redux'
    import reducer from './reducer'
    const store = createStore(reducer);
    export default store;
    

    初始页面数据,在reducer中管理默认数据

    首先在reducer中初始redux数据。进入reducer,在defaultState中加入变量num

    const defaultState = {
        num: 0
    }
    export default (state = defaultState, action) => {
        return state
    }
    

    在组件中调用redux的数据

    进入Page组件,先引入redux

    import store from '../store/index'
    

    或者

    import store from '../store'
    

    然后将redux中的state复制给组件中的state。并显示到span标签中。修改如下。

    import React, { Component } from 'react';
    import store from '../store'
    
    class Page extends Component {
        constructor(props) {
            super(props);
            this.state = store.getState() // 关键
        }
        render() { 
            return (
                <div>
                    <span>{this.state.num}</span> // 关键
                    <button>+</button>
                </div>
            );
        }
    }
     
    export default Page;
    

    现在redux中存的值就能显示到页面了。

    修改redux中的数据

    先为button按钮添加一个点击事件,让其出发addNum函数

    <button onClick={this.addNum.bind(this)}>+</button>
    

    在函数中向reducer提交一个"动作"add_num

    addNum() {
        const action = {
            type: 'add_num'
        }
        store.dispatch(action)
    }
    

    reducer中编写add_num的逻辑,代码如下

    export default (state = defaultState, action) => {
        if (action.type === 'add_num') {
            const newState = Object.assign(state)
            newState.num += 1
            return newState
        }
        return state
    }
    

    意思是当typeadd_num时,执行+1的操作

    store的自动推送策略

    通过上面的代码,每次点击+之后store中的值已经改变,但没有更新在组件上,于是需要在值变动时自动更新组件的state

    ...
    constructor(props) {
        super(props);
        this.state = store.getState()
        // 组件不能自动更新,需要订阅状态
        this.storeChange = this.storeChange.bind(this)  //转变this指向
        store.subscribe(this.storeChange) //订阅Redux的状态,每次state发生改变会触发里面的函数
    }
    ...
    storeChange() {
        this.setState(store.getState())
    }
    

    统一管理actionType

    在写redux action时会产生很多的action Types,项目小的时候没什么,但当项目很大的时候就不好管理这些action Types,比如,在组件中改动了type,那么也需要在reducer中去找到这个type并修改。为了统一管理action Types,创建一个单独的文件。
    store中创建actionTypes.js

    export const ADD_NUM = 'add_num'
    

    然后在reducer调用这个文件

    import { ADD_NUM } from './actionTypes'
    ...
    if (action.type === ADD_NUM) { // 关键
        const newState = Object.assign(state)
        newState.num += 1
        return newState
    }
    

    在组件中调用actionTypes.js

    import { ADD_NUM } from '../store/actionTypes'
    ...
    addNum() {
        const action = {
            type: ADD_NUM
        }
        store.dispatch(action)
    }
    

    这样就实现了action Types分开管理,可以减少代码冗余,而且在写错了常量名称的时候,浏览器和控制台都会报错。

    博客地址: http://www.iwowen.cn/2019/11/13/ck2xdq5sm0007g4bhn4zq0ssm.html

    展开全文
  • 在React中使用 Redux

    千次阅读 2018-09-14 14:10:26
    第一篇:使用webpack、babel、react、antdesign配置单页面应用开发环境 第二篇:使用react-router实现单页面应用路由 第三篇:优化单页面开发环境:webpack与react的运行时打包与热更新 第四篇...

    转载:https://www.jianshu.com/p/06f5285e2620

    这是Webpack+React系列配置过程记录的第六篇。其他内容请参考:

    这篇文章的主要内容包括:

    1. 修改一下之前存在的问题;
    2. 在框架中引入redux,使用一个例子简单介绍redux的使用方法;
    3. 其他redux辅助库。

    修复遗留问题

    1. webpack.prod.config.js中缺少了对path库的引用,执行构建npm run build:prod的时候失败。在文件开始的地方引入node.js的path库就可以了。
    2. package.json里面定义了一个build:dev的脚本,这个脚本其实有点多余,不过有时候需要打包测试版本的文件,所以还是需要存在。主要有个问题是webpack.dev.config.js中output节点下错误定义了path的值为根目录'/',这在使用npm start命令启动运行时打包的时候看不出问题,但是在使用npm run build:dev时会出现无法写文件到根目录的权限错误。只要把path的值改掉就可以。path: config.publicPath改成path: config.staticPath,publicPath: config.publicPath
    3. css-loader和less-loader导出的样式类名太长,还是把localIdentName中的path部分去掉比较好看。

    redux

    安装redux

    安装依赖的命令如下:

    npm install --save redux react-redux redux-thunk
    npm install --save-dev redux-logger
    

    redux不用说了,我是把它当成一个本地数据库使用,react-redux帮助你完成数据订阅,redux-thunk可以放你实现异步action,redux-logger是redux的日志中间件。

    关于redux与代码布局

    在开始介绍之前我想先就redux的使用发表一些自己的看法:

    前文说了我把redux当成一个本地数据库,因此我倾向于把redux封装类似于mvc中的Model的角色,独立为一层。这与另一种观点——我在公司的项目更倾向于把每个页面当成一个独立模块,每个模块维护自己的reducer和action的观点,有所出入。

    我的做法可以更好地实现reducer的复用。而对我自己来说更重要的好处是集中修改。更适合小项目或者独自开发一个项目的场景。

    我公司的项目的做法对多人协同开发更有利,毕竟每个人维护好自己的代码就可以了。公司项目的这种方法有几个问题让我比较难以接受:

    第一个是模块越多reducer和action的定义越多,很多时候这些代码都是差不多的。

    更重要的是第二个问题:模块数据在store里面的存储是直接在根state下面排列下来的,根state的数据格式样式有点像这样:

    {
        aModuleData:{...},
        bModuleData:{...},
        cModuleData:{...},
        dModuleData:{...},
        ...
    }
    

    项目的原意是希望每个模块的保持独立,但实际上使用的时候却是有极大的可能出现aModule同时使用aModuleData和bModuleData的情况。这跟每个人维护自己的代码的初衷有悖,也没有发挥好redux的真正能力。

    还有一个小问题是reducer的组织通常影响着应用数据state的样式,把reducer分散到每个模块之后,state的形式在代码上很难直管地反映出来,特别是当模块是动态加载的时候更甚。不过借助logger等工具可以解决。

    关于这块的争议Redux的教程中有提及。

    使用redux

    无论代码怎么布局,使用redux的方法主要还是三步曲:创建store、创建action、创建reducer。而在这之后才是与业务或者组件相关的数据处理和展示。

    先看一下我的做法的代码布局:

    代码布局

    1.创建store的代码集中在model/index.js中,model/actions/.js和model/reducer/.js里面分别是写action创建函数和reducer函数的地方,根据模块可以自己DIY。

    model/index.js的代码如下:

    model/index.js的代码

    2.  model/actions/index.js的代码如下:

    model/actions/index.js的代码

    3.  这里定义了一个名叫login的异步actionCreator以及三个普通的actionCreator。

     actionCreator被某个组件调用后会向store发送action,然后被reducer处理,                                                                                   reducer 定义在model/reducers/index.js中,代码如下:

    model/reducers/index.js的代码

    这就完成了三步曲了。上面的代码简单地模拟了登录的动作。登录页面用到的数据存放在loginPageData中,登陆后获取到的当前登录用户数据存储在实体数据entities中。

    接下来要把redux和react联系起来,也就是把redux的store中的数据交给react的组件使用。

    第一步需要挂载redux的store到react,为react提供数据支持。最简单的做法是找到应用的根组件(我这里是BasicExample.js),然后在它的render函数中最外层添加Providor标签。代码片段如下:

    挂载redux的store到react

    红线部分画出了改动点,从model/index.js中导出了store对象,通过react-redux提供的Providor标签挂载到react中,为react提供数据支持。

    看最后的红线中,我们在Home组件里面添加了这次的测试例子ReduxDemo。它的代码如下:

    ReduxDemo代码

    代码的重点在connect函数。这个函数也是由react-redux提供的。使用它可以包装普通的展示组件(这里是ReduxDemo——只负责展示数据),然后返回一个容器组件。connect函数通过第一个参数让展示组件订阅了来自store的数据;通过第二个参数让展示组件默认可以dispatch各种action。

    这个例子在ReduxDemo挂载完成后调用login接口模拟登陆。返回结果被塞到store中(数据格式由先前写好的reducers的组织方式决定)。页面根据store中的数据展示内容。由于login发出的远程请求是假的,所以这里总是失败,因此会显示失败的内容。

    关于redux的使用介绍到此结束。

    redux辅助库

    其实在上面的代码中我已经悄悄地提及了两个辅助库,也是我想在这里推荐的两个库:

    1. 开发工具redux-devtools:结合各种其他库可以实现可视化的调试界面。
    2. 数据规范化工具normalizr:规范化组织数据。经过三个项目的体验后,个人非常推荐使用这个库,可以让应用的数据组织更清晰、减少冗余数据、减少因数据刷新导致的性能影响。

    暂时不在这里展开介绍,有兴趣的可以到github上查一下文档。

    源码下载地址:https://pan.baidu.com/s/1dENYfuh



    作者:chardlau
    链接:https://www.jianshu.com/p/06f5285e2620 

    展开全文
  • 浅谈在React中使用Redux数据流(一)

    千次阅读 2017-05-30 20:38:59
    Ctrl+G:跳转到第几行 Ctrl+Tab:切换窗口 Command+W:关闭当前打开文件 Command+Q:关闭sublime Command+D:选择相同的单词,重复可选择下一个相同的单词 Command+L:选择行,重复可选择下一行 ...

    1、数据流是什么?为什么要用数据流?

    1)数据流是行为与响应的抽象。

    用户在页面上输入表单、按下按钮、拖拽等行为,页面会根据用户的行为给出一些响应,如刷新、跳转、局部刷新、Ajax局部刷新、数据更新等。以对象、方法来把它们抽象出来,这就是数据流。

    2)使用数据流可以帮助我们明确行为以及行为对应的响应。

    这与React的目标——状态图预测是密不可分的。

     

    2、React与数据流的关系

    React是纯V的框架,只负责视图,把视图做成了组件化,不涉及任何的数据和控制,需要数据流进行支撑才能完成一个完整的前端项目。

     

    3、主流的数据流框架有哪些?为什么使用Redux?

    1)Flux:Facebook在推出React时推出了一套官方适配的、配合React来实现的数据流,现在是一种单项数据流或单向数据绑定的思想,但它非常重、非常大、实用性不太强,因此很多人做了很多改进,出现了很多第三方的数据流框架,比较出名的有reFlux和Redux。

    2)reflux

    3)Redux:在很多第三方数据流框架中有一些优势:一是非常简单;二是它维护了一棵单一的状态树。

     

    4、单向数据流:

    1)MVC

    数据放在Model里,View来控制显示,Controller来做整体的管理。

    随着系统的庞大,会产生一些问题:交互时,当用户有一个Action时,这个Action会分发到各个Model,如:上网shopping,提交订单这一个动作会分解到有一条订单要记录下来、用户账户会发生变化、优惠信息会发生变化,物流信息会发生变化,会影响库存等。这么多Model都要更新,更新后页面上的多个View也会跟着变化,互相之间也会有影响,可能系统的状态会变得不可预测,不知道下单后页面会发生什么变化。

    2)Flux

    用户会有各种各样的Action(行为),所有的行为由一个统一的Dispatcher去分发,一个Action只能分发到若干个Store里面,Store保持着数据,也保存着当前页面的状态,根据用户的行为以及页面当前的状态,一个Store只能向视图层传递信息,不允许视图层反回来作用在Store上,视图就会发生变化,再由用户去传入新的Action,这样数据的流向是单向的。

     

    5、Redux概述

    Redux其实是Flux框架的一种实现方法。Redux与Flux的思想有点不同。

    大概的过程:当一个页面渲染完后,UI出现,用户其实是触发了UI上的一些Action,Action将会被送到Reducers方法里,Reducers将会更新Store,数据就是React开发中的State,State其实是Store的一部分,所有的视图层的东西,也就是组件,其实是由State来唯一决定的。



    6、React概述

    React可以认为有以下三部分组成:

    1)React.createClass():创建一个React组件

    属性this.props用于父子组件之间传递属性;

    属性this.state用于表示组件本身的状态,当state变化时,该组件会根据最新的state正确渲染出来;

    方法render()中定义组件渲染成什么样子,应该是怎么样的一种呈现,在其中写JSX;

    方法需要了解生命周期。

    2)ReactDOM.render():把组件(包括嵌套组件)渲染到页面的某个节点上。

    ReactDOM是在0.14版本之后才拆出来的,在之前是只有React,统称为React。

    3)各种属性

    一般不怎么用到,在此不作叙述。



    展开全文
  • React 中使用 Redux

    2019-06-11 12:06:46
    本文会通过三种方式实现一个简单到不能呼吸的计数器小例子,先用 React 实现,再慢慢引入 Redux 的内容,来了解什么是 Redux、为什么要使用 Redux 以及如何简单地使用 Redux。 1、React 实现计数器 上面这个例子用 ...

    这是一篇介绍 redux 的入门文章,欲知更多内容请查阅 官方文档

    本文会通过三种方式实现一个简单到不能呼吸的计数器小例子,先用 React 实现,再慢慢引入 Redux 的内容,来了解什么是 Redux、为什么要使用 Redux 以及如何简单地使用 Redux。

    1、React 实现计数器

    上面这个例子用 React 实现起来非常简单,初始化一个 creact-react-app,然后为了页面看起来更美观,在 index.html 加入 bootstrap 的 CDN,并修改 App.js 为如下内容就可以了。

    <link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet">
    复制代码
    import React, { Component } from 'react';
    
    export default class App extends Component {
    
      constructor(props) {
        super(props)
    
        this.state = {
          count: 0
        }
      }
    
      handleIncrement = () => {
        this.setState({
          count: this.state.count + 1
        })
      }
    
      handleDecrement = () => {
        this.setState({
          count: this.state.count - 1
        })
      }
    
      render() {
        return (
          <div className="container">
            <h1 className="text-center mt-5">{this.state.count}</h1>
            <p className="text-center">
              <button onClick={this.handleIncrement} className="btn btn-primary mr-2">Increase</button>
              <button onClick={this.handleDecrement} className="btn btn-danger my-2">Decrease</button>
            </p>
          </div>
        );
      }
    }
    复制代码

    这个例子非常简单,但是我们应该思考一下,React 是如何来改变这个数字的。

    有两个关键步骤,首先,它会从 state 中来读取初始值,然后当有点击事件发生了以后会去调用 setState 方法来改变 state 的值并重新渲染页面。这样就能看到页面上数字可以发生改变的效果了。

    那么问题来了,React 中一个组件里面维护数据只需要 state 和 setState 就可以轻松搞定。假如多个组件都需要维护这一份数据怎么办呢?

    2、为什么要使用 Redux

    了解 React 组件之间如何传递数据的人都应该知道,React 传递数据是一级一级地传的。就像如下的左图,绿色组件要想把某个时候的数据传递给红色的组件那么需要向上回调两次,再向下传一次,非常之麻烦。

    而 Redux 是怎么做的呢,Redux 有一个非常核心的部分就是 Store,Store 中管理的数据独立于 React 组件之外,如果 React 某个组件中的某个数据在某个时刻改变了(可以称之为状态改变了),就可以直接更改这个 Store 中管理的数据,这样其他组件想要拿到此时的数据直接拿就行了,不需要传来传去。

    需要说明的是,react 中有一个 context 也可以实现类似的功能,但它是一种侵入式写法,官方都不推荐,所以本文都不会提到它。

    这个过程看上去挺简单的,但是 Redux 为了做好这样一件事也是要经历一个比较复杂的过程的。

    接下来就开启 Redux 之旅吧。

    3、如何使用 Redux

    安装 redux:

    $ npm install --save redux
    or
    $ yarn add redux
    复制代码

    首先创建一个 src/Reducer.js

    Store 通常要和 Reducer 来配合使用,Store 存数据,Reducer 是个纯函数,它接收并更新数据。

    先创建一个 Reducer,为了简单,这里直接将需要的初始值写到 reducer 中的 state 中,state = 0 是给它的一个初始化数据(state 的值可以是一个对象,这里直接给一个数字),它还收接一个 action,当 action 的 type 为 'increment' 时就将 state + 1,反之减一。

    虽然这里把初始值写到了 reducer 中,但是真正存储这个 state 的还是 store,reducer 的作用是负责接收、更新并返回新的数据。

    同时也这里可以看出,Reducer 怎么更新数据,得看传入的 action 的 type 值了。

    export default (state = 0, action) => {
      switch (action.type) {
        case "increment":
          return state + 1;
        case "decrement":
          return state - 1;
        default:
          return state;
      }
    };
    复制代码

    然后创建 src/Store.js

    有了 Reducer 之后就可以来创建我们需要的 store 了,这个 store 是全局的,任何一个 react 组件想用它都可以引入进去。

    import { createStore } from 'redux';
    import Reducer from './Reducer';
    
    const store = createStore(Reducer)
    
    export default store;
    复制代码

    最后来修改我们的 App.js

    import React, { Component } from "react";
    + import store from "./Store";
    
    export default class App extends Component {
    +  onIncrement = () => {
    +    store.dispatch({
    +     type: "increment"
    +    });
    +  };
    
    +  onDecrement = () => {
    +    store.dispatch({
    +      type: "decrement"
    +    });
    +  };
    
      render() {
    +    store.subscribe(() => console.log("Store is changed: " + store.getState()));
    
        return (
          <div className="container">
    +        <h1 className="text-center mt-5">{store.getState()}</h1>
            <p className="text-center">
              <button className="btn btn-primary mr-2" onClick={this.onIncrement}>
                Increase
              </button>
              <button className="btn btn-danger my-2" onClick={this.onDecrement}>
                Decrease
              </button>
            </p>
          </div>
        );
      }
    }
    复制代码

    store.getState() 是用来获取 store 中的 state 值的。 store.subscribe() 方法是用来监听 store 中 state 值的,如果 state 被改变,它就会被触发,所以这个方法接收的是一个函数。subscribe() 方法也可以写到 componentDidMount() 里面。

    之前说了,要想改变 store 中 state 的值,就要传入一个 action 的 type 值,redux 规定,这个 action 的值需要由 store 的 dispatch 方法来派发。

    所以用 store.dispatch({type: 'increment'}); 这样简单的写法就轻松地给 reducer 传入了想要的值了,这个时候 state 的值就能变化了。

    现在就可以验证一下上面的操作了,手动改一下 state 的值,发现页面上的数据也改变了,说明页面上的数据从 store 中成功读取了:

    触发点击事件后,可以看到 state 的值成功的被改变了,说明用 store.dispatch() 来派发的这个 action 的 type 是成功的。

    那么页面上的数据为什么没有变化呢,这是因为 state 的值虽然被改变了,但是页面并没有重新渲染,之前在用 react 来实现这个功能的时候改变 state 调用了 setState() 方法,这个方法会同时重新渲染 render()。

    那么这里其实也是可以借助这个 setState() 方法的

    修改 App.js

    import React, { Component } from "react";
    import store from "./Store";
    
    export default class App extends Component {
    +  constructor(props) {
    +    super(props);
    
    +    this.state = {
    +      count: store.getState()
    +    };
    +  }
    
      onIncrement = () => {
        ...
      };
    
      onDecrement = () => {
        ...
      };
    
      render() {
    +    store.subscribe(() =>
    +      this.setState({
    +       count: store.getState()
    +      })
    +    );
    
        return (
          ...
          );
      }
    }
    复制代码

    这样借助 react 的 setState 方法就可以让 store 中的值改变时也能同时重新渲染页面了。

    一个简单的 redux 例子到这里也就完成了。

    3.1、抽取 Action

    上面的例子中,在 onClick 事件出触发的函数里面用了 store.dispatch() 方法来派发 Action 的 type,这个 Action 其实也可以单独抽取出来

    新建 src/Action.js

    export const increment = () => {
      return {
          type: "increment"
      };
    };
    
    export const decrement = () => {
      return {
          type: "decrement"
      };
    };
    复制代码

    修改 App.js

    import React, { Component } from "react";
    import store from "./Store";
    +import * as Action from './Action'
    
    export default class App extends Component {
      ...
    
      onIncrement = () => {
    +    store.dispatch(Action.increment());
      };
    
      onDecrement = () => {
    +    store.dispatch(Action.decrement());
      };
    
      render() {
        ...
      }
    }
    复制代码

    这样就把 dispatch 里面的内容单独抽取出来了,Action.js 里面的内容也就代表了用户鼠标进行的的一些动作。

    这个 Action.js 是还可以做进一步抽取的,因为 type 的值是个常量,所以可以单独提取出来

    新建 ActionTypes.js

    export const INCREMENT = 'increment'
    
    export const DECREMENT = 'decrement'
    复制代码

    然后就可以修改 Actions.js 了

    +import * as ActionTypes from './ActionType';
    
    ...
    复制代码

    同样的 Reducer.js 的 type 也可以修改下

    +import * as ActionTypes from './ActionType';
    
    export default (state = 0, action) => {
      switch (action.type) {
    +    case ActionTypes.INCREMENT:
          return state + 1;
    +    case ActionTypes.DECREMENT:
          return state - 1;
        default:
          return state;
      }
    };
    复制代码

    到这里一个包含 Action、Reducer、Store、dispatch、subscribe、view 的完整 redux 例子就实现了,这里的 view 指的是 App.js 所提供的页面也就是 React 组件。

    这个时候再来看一眼题图就很非常好理解 Redux 整个工作流程了:

    4、如何使用 react-redux

    在 react 中使用 redux 其实是还可以更加优雅一点的。redux 还提供了一个 react-redux 插件,需要注意的是这个插件只起到辅助作用并不是用来替代 redux 的。

    至于使用了它如何变得更加优雅,这个先从代码开始说起:

    安装 react-redux:

    $ npm install --save react-redux
    or
    $ yarn add react-redux
    复制代码

    每个组件中要用到 store,按之前的方法需要单独引入,这里还可以换一种方式,直接在最顶层组件将它传进去,然后组件想用的时候再接收:

    修改 index.js,这是个最顶层组件,将 store 在这里引入并向下传递

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

    修改 App.js,在这里引入用 connect 来接收 store,然后就可以用 this.props 来使用 dispatch 了,state 则用一个函数来接收一下就可以使用了。

    import React, { Component } from "react";
    import * as Action from "./Action";
    +import { connect } from "react-redux";
    -import store from "./Store";
    
    +class App extends Component {
    -  constructor(props) {
    -    super(props);
    
    -    this.state = {
    -      count: store.getState()
    -    };
    -  }
    
      onIncrement = () => {
    +    this.props.dispatch(Action.increment());
      };
    
      onDecrement = () => {
    +    this.props.dispatch(Action.decrement());
      };
    
      render() {
    -    store.subscribe(() =>
    -      this.setState({
    -        count: store.getState()
    -      })
    -    );
    
        return (
          <div className="container">
    +        <h1 className="text-center mt-5">{this.props.count}</h1>
            <p className="text-center">
              <button className="btn btn-primary mr-2" onClick={this.onIncrement}>
                Increase
              </button>
              <button className="btn btn-danger my-2" onClick={this.onDecrement}>
                Decrease
              </button>
            </p>
          </div>
        );
      }
    }
    
    +const mapStateToProps = state => ({
    +  count: state
    +});
    
    +export default connect(mapStateToProps)(App);
    复制代码

    你会意外地发现竟然不需要用 setState 方法来重新渲染页面了,redux 已经帮我们做这件事情了。你可能会对 connect()() 这种写法有疑问,它是一个柯里化函数,底层是怎么实现的本文不讨论,现在只需要知道传入什么参数,怎么用它就可以了。

    4.1、处理 Action

    其实使用了 react-redux 之后我们不仅不需关心如何去重新渲染页面,还不需要去手动派发 Action,直接在 connect 方法中把 Action 传进去,然后直接调用就行了

    在上面的基础上再次修改 App.js:

    import React, { Component } from "react";
    import * as Action from "./Action";
    import { connect } from "react-redux";
    
    class App extends Component {
    -   onIncrement = () => {
    -     this.props.dispatch(Action.increment());
    -   };
    
    -   onDecrement = () => {
    -     this.props.dispatch(Action.decrement());
    -   };
    
      render() {
    +    const { increment, decrement } = this.props;
    
        return (
          <div className="container">
            <h1 className="text-center mt-5">{this.props.count}</h1>
            <p className="text-center">
    +          <button className="btn btn-primary mr-2" onClick={() => increment()}>
                Increase
              </button>
    +          <button className="btn btn-danger my-2" onClick={() => decrement()}>
                Decrease
              </button>
            </p>
          </div>
        );
      }
    }
    
    const mapStateToProps = state => ({
      count: state
    });
    
    +export default connect(mapStateToProps,Action)(App);
    复制代码

    到这里你应该就能体会到使用 react-redux 插件的便捷性了,其实它还有其他很多优点,这里不再一一举例。

    5、如何使用多个 reducer

    redux 中只需要有一个全局的 store,那么如果还需要管理其它状态,可能就需要用到多个 reducer,redux 中提供了一个 combineReducers 可以来将多个 reducer 连接起来。

    这里再来演示一下 combineReducers 的用法,为了尽量少修改文件,我这里并没有创建文件夹来分类管理,实际使用过程中不同作用的文件应该放到不同的文件夹中。

    创建文件 src/Reducer2.js

    export default (state = "hello", action) => {
      switch (action.type) {
        default:
          return state;
      }
    };
    复制代码

    创建 src/CombineReducer.js

    import { combineReducers } from 'redux';
    
    import count from './Reducer';
    
    import hello from './Reducer2';
    
    const rootReducer = combineReducers({
        count,
        hello
    })
    
    export default rootReducer;
    复制代码

    修改 Store.js

    import { createStore } from 'redux';
    +import rootReducer from './CombineReducer';
    
    +const store = createStore(rootReducer)
    
    export default store;
    复制代码

    修改 App.js

        ...
        return (
          <div className="container">
    +        <h1 className="text-center mt-5">{this.props.text}{this.props.count}</h1>
            ...
          </div>
        );
      }
    }
    
    const mapStateToProps = state => ({
      count: state.count,
    +  text: state.hello
    });
    ...
    复制代码

    效果如下,可以在 store 中读取到相应的值:

    最后,完整的代码在这里:github.com/bgrc/react-…

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

    展开全文
  • 为什么要用react-router-redux

    千次阅读 2018-05-30 18:53:29
    react-router-reduxreact-...例如,react-router 跳转需要调用 router.push(path),集成了react-router-redux 就可以通过dispatch的方式使用router,例如跳转可以这样做 store.dispatch(push(url))。本质上...
  • react-redux中实现页面跳转

    千次阅读 2018-05-05 21:08:22
    react-redux中实现页面跳转 由于react-router版本变化,网上好些资料跑步起来。 当前使用版本如下: "react-router": "^4.0.0", "react-router-dom": "^4.2.2", &...
  • 1、组件引入store 2、constructor构造器方法,重写store.subscribe方法(该方法即是监听state状态改变的放过) 组件完整代码如下: import React, { Component } from 'react' import CSSModules from ...
  • react -redux之provider作用小析

    千次阅读 2016-12-06 13:51:48
    Provider 是 react-redux 库提供的,redux 本身并不强制依赖它,然而问题是 redux 本身也不依赖 react。作为一个纯粹的 data layer,redux 并不关心你用什么视图引擎,所以如何访问 store 是你自己需要考虑的事情...
  • 登录组件的目录结构 登录调用函数,调用action,将...然后使用调试工具redux-devtools可以看到当前多了token的节点 接下来是其他页面获取token 只需要将state的数据取出来,连接到当前的组件的prop属性 ...
  • 为什么要存储react-redux中的数据? 当页面刷新之后,redux中的数据会回到初始值,之前存储到redux中的数据也就不复存在了。废话不多说,直接上代码: reducer文件中: let shopDetailInfo = sessionStorage....
  • React——react-redux

    千次阅读 2018-10-12 17:43:28
    因为自己是Vue开发者,所以会以Vuex的角度来看React的状态...说起 react-redux 就不得不先说 reduxRedux redux 是一个数据设计架构,专注于状态管理,和 react 解耦 单一状态,单向数据流 redux 有4个...
  • 最简单的ReactRedux整合的例子

    万次阅读 2017-07-25 13:29:06
    react redux demo
  • reducer改变了state的值,但是页面没有重新渲染
  • 不要再问React Hooks能否取代Redux

    千次阅读 2019-09-13 01:44:33
    译者 | 连城译文 | https://zhuanlan.zhihu.com/p/81126574作者 | Max González原文 | https://me...
  • 26.react-reduxredux的区别

    千次阅读 2019-01-22 15:27:48
    redux使用回顾和核心 1.组件如何触发store的state改变 createStore(reducer) 引入store store.dispatch(action)方法 reducer根据不同action type 返回新的state部分 2.组件如何监听store的改变从而改变...
  • 为什么 react 使用 redux

    千次阅读 2017-07-11 00:15:18
    背景作为一名后端工程师,我最近学习前端 react 知识,准备转全栈工程师,学 react 势必要学习 redux ,初学 redux 的时候,觉得 redux 很鸡肋,根据我的经验来看,我认为 redux 的设计非常的反设计原则,为什么...
  • ReactNative-Redux实际应用

    千次阅读 2016-10-13 22:37:18
    Redux刚开始我也是一头雾水,文章看着也是懵懵懂懂,经过多方查看别人写的文章,自己动手实现回头看别人写的也就那么回事。这里还是使用干活集中营的妹子接口来真实操作下Redux,建议一定要动手写写,理解不动就...
  • 一般在react项目,我们通过reduxreact-redux来存储和管理数据,但是使用redux存储数据时,会有一个问题,如果用户刷新了页面,那么通过redux存储的全局数据就会被重置,比如登录状态等。 这个时候有没有解决办法...
  •   如果您学习Redux,当然你可能很快知道Redux 的基本使用,但是如果要项目更好的使用它,对于redux 一些的概念性问题你可以就要花费一些时间去实践。   这里主体阐述下面的实例应用和说明教程...
  • reactredux使用websocket

    千次阅读 2019-01-17 19:36:28
    近期,小编网上搜索各种资料,呕心沥血,终于初步在react中加入了websocket!长话短说,现在npm包结构的websocket很多,如果是node服务端,或者服务端用node做中间层,可以考虑socket.io,小编这里给大家介绍一种...
1 2 3 4 5 ... 20
收藏数 24,820
精华内容 9,928
关键字:

在react中使用redux