react-redux的基本用法

注意:读懂本文须要具有redux基础知识,css

注明:本文旨在说明如何在实际项目中快速使用react-redux,限于篇幅,本文对具体的原理并未作分析,请参考redux官网html

我一直觉得我写了一篇关于react-redux的文章,昨天在翻个人博客时才发现没有。vue

前几天写了vue的状态管理 vuex,Vue中的状态管理器 - Vuex,讲了vue中状态管理的用法,总体感受是很简单的,react

状态和路由都是官方本身整合的,不论是文档仍是用来都比较顺滑,而redux的门槛要比vuex高很多。webpack

题外话:为何vue这么好用你还要搞react呢,个人感受是,vue就像qq,react就像facebook,虽然均可以社交,可是味道不同,各有所好,web

另外react-native能够作app目前vue不能,若是外包我选择vue(快),要作一个长期的网站我会用react。vuex

说了一大堆,开始正文:npm

前面我写了一篇文章:快速搭建一个vue开发环境,用到了vue官方的脚手架,一样,react官方也有一个,相似功能的:create-react-app。redux

补充一点额外常识:vue中路由和状态管理都是官方整合的,属于官方库,而在react中,只有react! 路由和状态管理由第三方库提供。react-native

全局安装 create-react-app

npm install -g create-react-app

建立一个 test的项目

create-react-app test

经过这句话搭建的环境已经能够正常跑起来了,集成了webpack,和热加载,更以前vue搭建那个环境同样,不过没有路由和状态管理,

这一篇我只讲react+状态管理,路由之后单独写,或者可能不用写了,路由是很简单的,看一下就知道怎么用。

在项目目录下执行 npm run start 项目就跑起来了,尝试修改一下 src/App.js,页面辉自动从新加载。

安装redux

#说明:redux是一个通用状态管理库,能够用于任何现代化框架,好比vue,react,angular等,不局限于react,均可以直接使用redux。

在react中, 你除了能够直接使用redux外,redux针对react推出了react-redux绑定,使用起来更规范和顺滑。

本文要讲解的是 react-redux的用法,并假设你已经有了redux的基础概念。

npm install redux react-redux redux-thunk --save
// redux是核心,react-redux是react的绑定,redux-thunk是异步中间件

如今假设咱们网页上有三个数据须要让redux来管理,分别是 用户的信息name,sex和系统的背景颜色bgcolor。

在src下新建actions目录,在目录下面新建userAction.js文件,

在src下新建reducers目录,userReducer.js,rootReducer.js两个文件,

在src下新建store.js 文件

整个流程是这样的, view层获取store中的数据渲染页面,当在view中须要变动store中的数据的时候,就发送一个action过去,接收这个action的不是

store,而是reducer,reducer更改数据后更新state,在这个更新过程当中会触发view层的渲染逻辑,而后view层从新渲染。

在一个页面中会有不少操做要更改store中的数据,每个操做就对应一个action。

userAction.js 代码:

export const nameAction = (name) =>{
    return {
        type: 'name',
        payload: name
    }
}

export const sexAction = () =>(dispatch)=>{
    setTimeout(()=>{
        dispatch({
            type: 'sex',
            payload: '男'
        })
    },2000)
}

第一个action是用来更更名字的,第二个action是用来更改性别的,这两个action看起来有差别,第一个action返回一个对象,而第二个action

是一个高阶函数,返回了一个函数。

第一个action是普通的操做,发送这个action后store中的数据立马就会更新,而第二个action是用来处理异步数据的,能够把这个地方的setTimeout替换成一个

网络请求,好比我发送了一个更新资料的action,可是这个更新要从服务器动态获取,那么就只能用第二种方式,用第二种方式的前提是加载了thunk中间件,不然第二种方式会报错。

userReducer.js 代码:

let init = {
    'name': '张三',
    'sex': '女'
}
export default (state=init,action)=>{
    switch(action.type) {
        case 'name':
            state.name = action.payload
            return {...state}
        case 'sex':
            state.sex= action.payload
            return {...state}
        // 在没有匹配的状况下必定要返回旧的state
        default:
            return state
    }
}

reducer是纯函数,第一个参数是当前state,第二个参数是接收的action,reducer经过action的type来判断要处理的逻辑,

注意,reducer必定要返回新的state才能触发view从新渲染,因此这里返回的 {...state} 就是一个新对象,最后若是没有匹配到

对应action,就返回旧的state。

rootReducer 代码:

import {combineReducers} from 'redux'
// import systemReducer from './systemReducer'
import userReducer from './userReducer'

// 包含全部的计算函数
export default combineReducers({
    // system: systemReducer,
    user: userReducer
})

前面一个reducer是处理用户板块action的,一个网站有不少板块,好比系统设置,若是把全部的处理都放到一个reducer中,那么这个函数会很是庞大,

因此在文件组织上咱们把 reducer按照类型拆分红多个reducer,最后用redux提供的combineReducer函数进行合并,rootReducer就是干这事的

store.js 代码:

import {createStore,applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/rootReducer'

export default function configureStore() {
    return createStore(
        rootReducer, 
        applyMiddleware(thunk)
    )
}

这段代码是配置store的,经过createStore函数来建立一个store,第一个参数是 reducer,第二个参数是加载中间件,这个地方加载了thunk中间件,是redux官方提供的,

专门用来处理异步action,上面的userAction中设置sex时旧采用了异步的方式。

index.js 代码:

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import configureStore from './store';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
    <Provider store={configureStore()}>
        <App />
    </Provider>,
    document.getElementById('root'));

serviceWorker.unregister();

前面已经搞定了action,reducer,store,这个文件就是应用redux道项目中,主要关注 Provider和 store两个地方,Provider时redux提供给react的包装器,

store属性用来注入状态管理。这个地方就不解释内部原理了,只要知道这么用就行。

App.js 代码:

import React, { Component } from 'react';
import {connect} from 'react-redux';
import {nameAction,sexAction} from './actions/userAction';
// import {bgcolorAction} from './actions/systemAction';
// import logo from './logo.svg';
import './App.css';

class App extends Component {

  componentDidMount() {}
  render() {
    return (
      <div className="App" >
        <header className="App-header" >
          {/* <p style={{color:this.props.system.backgroundColor}}> */}
          <p>
            name:{this.props.user.name} <br/>
            sex:{this.props.user.sex} <br/>
          </p>
          <button onClick={()=>this.props.name('利萨')}>更更名字</button>
          <button onClick={()=>this.props.sex()}>更改性别</button>
          {/* <button onClick={()=>this.props.bgcolor()}>更改颜色</button> */}
          <pre>
            { JSON.stringify(this.props) }
          </pre>
        </header>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  ...state
})
const mapDispatchToProps = dispatch=>({
  name: (name)=>dispatch(nameAction(name)),
  sex: ()=>dispatch(sexAction())
  // bgcolor: ()=>dispatch(bgcolorAction())
})

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

这个地方关注 connect,mapStateToProps,mapDispatchToProps,

connect是redux提供的链接器,任何要使用redux这一套的view就必须使用connect链接,mapStateToProps是将store中的数据复制到

本view的props中,并且是实时同步的,

mapDispatchToProps 是将actioni复制到本view的props中,让view拥有发送action的机会。

相关文章
相关标签/搜索