React相关知识点:关于Redux

为何用Redux

一些小型项目,只使用 React 彻底够用了,数据管理使用props、state便可,那何时须要引入Redux呢? 当渲染一个组件的数据是经过props从父组件中获取时,一般状况下是A –> B,但随着业务复杂度的增长,有多是这样的:A –> B –> C –> D –> E,E须要的数据须要从A那里经过props传递过来,以及对应的E –> A逆向传递callback。组件BCD是不须要这些数据的,可是又必须经由它们来传递,这样不太友好,并且传递的props以及callback对BCD组件的复用也会形成影响。或者兄弟组件之间想要共享某些数据,也不是很方便传递、获取等。诸如此类的状况,就有必要引入Redux`了。

注:其实 A --> B --> C --> D --> E 这种状况,React不使用props层层传递也是能拿到数据的,使用Context便可。javascript

Redux 的三大基本原则

redux的核心概念就是store、action、reducer

约法三章

State 是只读的 react文档中说唯一改变 state 的方法就是触发 action,奇怪的是 咱们说State是只读的,可是为啥如今又说能够修改了呢,其实咱们并非直接修改state,action”是用来向 store 表示要修改 state 的载体。因此咱们并无直接设置state的方法,使用了dispatch(action) 发送 action 至 store 是惟一改变 state 的方式

store

  1. UI惟一数据来源;
  2. 维持应用的 state; 
  3. 提供 getState() 方法获取 state; 
  4. 提供 dispatch(action) 方法更新 state; 
  5. 经过 subscribe(listener) 注册监听器; 经过 subscribe(listener) 返回的函数注销监听器。


action

必须拥有type属性,用来描述发生什么,action经过reducer处理生成newState后才可以更改store信息。可是为了更好的语义编程,Redux经过语句store.dispatch(action)来更新store,reducer对action的处理在内部处理。
java

reducer

仅仅只是根据action.type处理一下须要更新的state
react

建立目录


建立Store模块 数据源

//store/index.js编程

/*引入createStore 是用来建立一个数据源对象保存咱们的数据的*/

import { createStore, applyMiddleware, compose } from 'redux';
import { createLogger } from 'redux-logger';
//引用数据源
// store是引用的reducer
// action会触发reducer
import allreducers from './reducers/index';
//数据处理后会返回给数据源 才能取到最新的数据  在根组件index里获取


const logger = createLogger();
const store = createStore(
    allreducers,
    applyMiddleware(logger)
)
console.log(store)
function listerner () {
    store.getState();
}
store.subscribe(listerner);

export default store;复制代码


传入Store

Store保存了整个应用的单一状态树,全部容器组件都须要从store中读取,咱们能够store做为属性传递给每一个组件,子组件经过props获取,可是若是嵌套过深,写起来会很麻烦。还好,react-redux提供一个叫provider的组件,他可让全部组件均可以访问到store(他的实现原理其实是利用了react的context功能),而没必要显示的一层层传递了。
import { Provider } from 'react-redux'
import store from './store';


ReactDOM.render(
   <Provider store={store}> <BrowserRouter> {routes } </BrowserRouter> </Provider>,
    document.getElementById('app')
);复制代码

建立Reducer 处理业务数据

//reducers/index.jsredux

import * as Types from 'src/store/constants'
import { combineReducers } from 'redux';

const initState = {
    isLogin: "未登陆",
    themecolor: "red",
    count: 0
}


const loginReducer = (state = initState.isLogin ,action) => {
    switch (action.type) {
        case Types.LOGIN_TYPE:
            return state = action.isLogin
        default:
            return state
    }
}

const themeReducer = (state = initState.themecolor ,action) => {
    switch (action.type) {
        case Types.THEME_TYPE:
            return state = action.themecolor
        default:
            return state
    }
}

const counterReducer = (state = initState.count, action) => {
    switch(action.type) {
        case Types.ADD_TYPE: return state + 1;
        default: return state;
    }
}

export default combineReducers({
    isLogin:loginReducer,
    themecolor:themeReducer,
    count:counterReducer
})复制代码

注意:combineReducers() 函数的做用是把多个 reducer 合并成一个最终的 reducer 函数。
bash

常量统一保存

//constants/index.jsapp

/*常量统一保存,便于管理*/
export const LOGIN_TYPE = "LOGIN_TYPE"
export const THEME_TYPE = "THEME_TYPE"
export const ADD_TYPE = "ADD_TYPE"复制代码

建立Action模块

actions/index.jside

import * as Types from 'src/store/constants'
export const loginAction = function(isLogin) {
    return {
        type: Types.LOGIN_TYPE,
        isLogin
    }
}

export const themeAction = function(themecolor) {
    return {
        type: Types.THEME_TYPE,
        themecolor
    }
}

export const addAction = () => {
    return {
        type: Types.ADD_TYPE
    }
}复制代码

组件调用函数式编程

import React, {PureComponent} from "react"
import store from 'src/store'
import { loginAction,themeAction,addAction } from 'src/store/actions'

const counterfn = () => {
    document.getElementById("counter").innerHTML = store.getState().count
}
store.subscribe(counterfn);
class NwdLogin extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
    }
    render () {
        var state = store.getState();
        return (
            <div> <div id="counter"></div> <div> <button onClick={() => store.dispatch(addAction())}>add </button> </div> </div>
        )
    }
}
export default NwdLogin复制代码



函数

注意:在不使用react-redux的状况下 必须使用store.subscribe(listener), store更新后回调listener,回调函数里面能够调用store.getStore()来获取更新后得state哟~

结合 react-redux使用

react-redux,redux和react的桥梁工具。 react-redux将组建分红了两大类,UI组建component和容器组件container。 

UI组件:

  1. 只负责 UI 的呈现,
  2. 不带有任何业务逻辑 没有状态(即不使用this.state这个变量) 
  3. 全部数据都由参数(this.props)提供 不
  4. 使用任何 Redux 的 AP

容器组件:

  1. 负责管理数据和业务逻辑,不负责 UI 的呈现 
  2. 带有内部状态 
  3. 使用 Redux 的 API

1)经过connect方法将React组件和Redux链接起来,react-redux 中引入了 connect

import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
class NwdLogin extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
    }
    render () {
        console.log(this.props)
        return (
            <div> {this.props.isLogin} <button onClick={() => this.props.loginAction("已登陆")}>设置登陆状态</button> <button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button> </div>
        )
    }
}
const mapStateToProps = (state,ownProps) => {
    return {
        isLogin: state.isLogin,
        themecolor: state.themecolor
    }
}

const mapDispatchToProps = ((dispatch,ownPorps) => {
    return {
        loginAction: (isLogin) => dispatch({
            type: "LOGIN_TYPE",
            isLogin: isLogin
        }),
        themeAction: (themecolor) => dispatch({
            type: "THEME_TYPE",
            themecolor: themecolor
        })
    }
})

export default connect(mapStateToProps,mapDispatchToProps)(NwdLogin)复制代码





1)connect()() 其实这儿是两次函数调用。首先。connect() 返回了一个函数,而后咱们马上调用了这个函数并给它传递进第二个括号内的参数。第二个参数通常是一个 React 组件这是一种常见的“函数式编程”的写法。

2)connect() 的第一个参数是个返回了一个对象的函数 mapStateToProps,这个对象的属性将会变成 React 组件中的“props”的属性,你能够看到他们的值来自 store 的 state。这里我把这第一个参数命名为“mapStateToProps”,如命名所示,是但愿它来将全局 states 转化成本地 component 的 props。 mapStateToProps() 将会接收到一个携带着完整的 Redux store 的参数 store,而后抽出本地组件须要的 states 转换成 props。

3)

若是不写mapDispatchToProps,只能本身手动调用this.props.dispatch()

import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'
class NwdLogin extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
    }
    render () {
        console.log(this.props)
        return (
            <div> {this.props.isLogin} <button onClick={() => this.props.dispatch(loginAction("已登陆"))}>设置登陆状态</button> <button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.dispatch(themeAction("#fff"))}>设置themecolor状态{this.props.themecolor}</button> </div>
        )
    }
}
const mapStateToProps = (state,ownProps) => {
    return {
        isLogin: state.isLogin,
        themecolor: state.themecolor
    }
}

/*const mapDispatchToProps = ((dispatch,ownPorps) => { return { loginAction: (isLogin) => dispatch({ type: "LOGIN_TYPE", isLogin: isLogin }), themeAction: (themecolor) => dispatch({ type: "THEME_TYPE", themecolor: themecolor }) } })*/

export default connect(mapStateToProps)(NwdLogin)复制代码

react-redux中connect的装饰器用法@connect

import React, {PureComponent} from "react"
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'

@connect(
    state => {
        return {
            isLogin: state.isLogin,
            themecolor: state.themecolor
        }
    },
    {
        loginAction,
        themeAction,
        addAction
    }
)
class NwdLogin extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
    }
    render () {
        console.log(this.props)
        return (
            <div> {this.props.isLogin} <button onClick={() => this.props.loginAction("已登陆")}>设置登陆状态</button> <button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button> </div>
        )
    }
}
export default NwdLogin
复制代码

redux的bindActionCreators

bindActionCreators是redux的一个API,做用是将单个或多个ActionCreator转化为dispatch(action)的函数集合形式。 开发者不用再手动dispatch(actionCreator(type)),而是能够直接调用方法。


import React, {PureComponent} from "react"
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { loginAction,themeAction,addAction } from 'src/store/actions'

@connect(
    state => {
        return {
            isLogin: state.isLogin,
            themecolor: state.themecolor
        }
    },
    dispatch => bindActionCreators({loginAction,themeAction,addAction},dispatch)
)
class NwdLogin extends React.Component {
    constructor(props){
        super(props)
    }
    componentDidMount() {
    }
    render () {
        console.log(this.props)
        return (
            <div>
                    {this.props.isLogin}
                    <button onClick={() => this.props.loginAction("已登陆")}>设置登陆状态</button>
                    <button style={{backgroundColor:this.props.themecolor}} onClick={() => this.props.themeAction("#fff")}>设置themecolor状态{this.props.themecolor}</button>
            </div>
        )
    }
}
export default NwdLogin

复制代码
相关文章
相关标签/搜索