react状态管理器

Posted hy96

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react状态管理器相关的知识,希望对你有一定的参考价值。

1、回顾

2、状态管理器

redux

redux + redux-thunk (redux-promise/redux-saga)

redux + redux-thunk + react-redux

redux + react-redux

mobx + mobx-react

3、redux - 整合

cnpm i redux redux-thunk react-redux -S

  • src文件夹下创建 store/index.js
// 1、引入对应的模块
import { createStore } from 'redux';

// 2、创建纯函数,用来存放应用需要的状态 ----- 必须给返回值
// 纯函数有两个参数
// state 代表应用的初始化装填
// action 代表的是改变state触发的行为
const reducer = () => {
  
}

// 3、创建仓库
const store = createStore(reducer);

// 4、暴露仓库
export default store;
  • 纯函数reducer
// 2、创建纯函数,用来存放应用需要的状态 ----- 必须给返回值
// 纯函数有两个参数
// state 代表应用的初始化装填
// action 代表的是改变state触发的行为
const reducer = (state = {
  bannerlist: [],
  prolist: [],
  cartlist: []
}, action) => {
  // type 表示要改变哪一个初始化数据的标识
  // data 表示需要改变的数据
  const { type, data } = action;
  // 条件判断 改变状态 依靠对象合并
  switch (type) {
    case 'CHANGE_BANNER_LIST':
      return Object.assign({}, state, { bannerlist: data });
    case 'CHANGE_PRO_LIST':
      return {...state, ...{prolist: data}};
    case 'CHANGE_CART_LIST':
      return Object.assign({}, state, { cartlist: data });
    default:
      return state;
  }
}
  • 入口文件处使用 仓库 index.js
import store from './store';

function render () {
  ReactDOM.render(
    <Router>
      <Switch>
        <Route path="/" component = { App } />
      </Switch>
    </Router>,
    document.getElementById('root')
  )
}
render()

// 检测到状态管理器状态发生改变,重新执行render函数
// 状态的改变引起视图的二次渲染
store.subscribe(render)
  • 页面处获取状态或者改变状态

views/home/index.jsx

import React, { Component } from 'react';
import store from '@/store'; // +++++++++++++++++++++
import { getBannerlist, getProlist } from '@/utils/api' // ++++++++++++++++
export default class extends Component {
  componentDidMount () {
    console.log(store)
    // console.log(store.getState()) // ++++++++++++++++++++++++++++
    getBannerlist().then(data => {
      // 改变状态管理器状态
      store.dispatch({ // +++++++++++++++++++++++++++++++++++++
        type: 'CHANGE_BANNER_LIST',
        data: data.data
      })
    })
    getProlist().then(data => {
      store.dispatch({
        type: 'CHANGE_PRO_LIST',
        data: data.data
      })
    })
  }
  render () {
    console.log(store.getState())
    let { bannerlist, prolist } = store.getState() // +++++++++++++
    return (
      <div className="box">
        <header className = "header"></header>
        <div className = "content">
          {
            bannerlist.map(item => {
              return (
                <p key={ item.bannerid }>{ item.img }</p>
              )
            })
          }
          {
            prolist.map(item => {
              return (
                <p key={ item.proid }>{ item.proname }</p>
              )
            })
          }
        </div>
      </div>
    )
  }
}

此时发现解决了问题,但是所有的状态都在一个文件的内部,在某些需求时不合理,可以将状态按照模块划分
views/home/store.js views/cart/store.js

4、redux + react-redux

redux 负责状态 ---- 属于js的状态管理模式

react-redux redux在react中的一个插件

  • store/index.js 不用改变
import { createStore } from 'redux';

const reducer = (state = {
  bannerlist: [],
  prolist: [],
  cartlist: []
}, action) => {
  const { type, data } = action;
  switch (type) {
    case 'CHANGE_BANNER_LIST':
      return { ...state, ...{ bannerlist: data } }
    case 'CHANGE_PRO_LIST':
      return { ...state, ...{ prolist: data } }
    case 'CHANGE_CART_LIST':
      return { ...state, ...{ cartlist: data } }
    default:
      return state
  }
}

const store = createStore(reducer);

export default store;
  • 入口页面处改变
import store from './store';
import { Provider } from 'react-redux';

ReactDOM.render(
  <Provider store = { store }>
    <Router>
      <Switch>
        <Route path="/" component = { App } />
      </Switch>
    </Router>
  </Provider>,
  document.getElementById('root')
)
  • 组件的改变 ---- 页面组件的改变

react-redux 将页面分为 容器组件和UI组件,容器组件负责 页面的业务逻辑,UI组件只负责 渲染组件

容器组件由UI组件生成,容器组件负责提供UI组件的数据以及执行UI组件需要的业务逻辑

views/home/UI.jsx ---- UI组件 ----- 通常写的页面

// UI组件
import React, { Component } from 'react';

class Com extends Component {
  componentDidMount () {}
  render () {
    return (
      <div className="box">
        <header className="header">头部</header>
        <div className="content">内容</div>
      </div>
    )
  }
}

export default Com;

views/home/index.jsx ---- 容器组件 ------ 状态以及业务逻辑

// 容器组件
import { connect } from 'react-redux';
import UI from './UI';

const Com = connect()(UI);

export default Com;

ui组件不做任何的业务逻辑处理

  • 容器组件获取状态管理器中的数据,UI组件通过this.props访问数据

views/home/index.jsx

// 容器组件 --- connect --- react的高阶组件
import { connect } from 'react-redux';
import UI from './UI';

// 获取状态管理器中的数据 --- 必有返回值 ++++++++++++++++++++++++++++
const mapStateToProps = (state) => { // state 是全部的状态
  // state { bannerlist: [], prolist: [], cartlist: [] }
  return {
    bannerlist: state.bannerlist,
    prolist: state.prolist
  }
}

const Com = connect(mapStateToProps)(UI); // +++++++++++++++++++++++++

export default Com;

views/home/UI.jsx

render () {
  // UI组件内部通过this.props获取容器组件提供的数据
  let { bannerlist, prolist } = this.props; // ++++++++++++++++
  console.log('bannerlist', bannerlist)
  console.log('prolist', prolist)
  return (
    <div className="box">
      <header className="header">头部</header>
      <div className="content">内容</div>
    </div>
  )
}
  • 容器组件 实现 UI组件需要的业务逻辑,请求数据改变 bannerlist 以及 getProlist

views/home/index.jsx

import { getBannerlist, getProlist } from '@/utils/api'

// 设计UI组件需要使用的业务逻辑 -- 必有返回值
const mapDispatchToProps = (dispatch) => { // store.dispatch
  return {
    getBannerlist () { // ui组件通过 this.props.getBannerlist() 调用触发
      console.log('请求轮播图数据')
      getBannerlist().then(data => {
        dispatch({ // 更改状态管理器中的数据
          type: 'CHANGE_BANNER_LIST',
          data: data.data
        })
      })
    },
    getProlist () {// ui组件通过 this.props.getProlist() 调用触发
      console.log('请求列表数据')
      getProlist().then(data => {
        dispatch({
          type: 'CHANGE_PRO_LIST',
          data: data.data
        })
      })
    }
  }
}


const Com = connect(mapStateToProps, mapDispatchToProps)(UI); // +++++++

views/home/UI.jsx

// UI组件
import React, { Component } from 'react';

class Com extends Component {
  componentDidMount () {
    this.props.getBannerlist(); // ++++++++++++++++++++
    this.props.getProlist(); // ++++++++++++++++
  }
  render () {
    console.log(this.props)
    // UI组件内部通过this.props获取容器组件提供的数据
    let { bannerlist, prolist } = this.props;
    console.log('bannerlist', bannerlist)
    console.log('prolist', prolist)
    return (
      <div className="box">
        <header className="header">头部</header>
        <div className="content">
          {
            bannerlist.map(item => (
              <p key={ item.bannerid }>{ item.img }</p>
            ))
          }
          {
            prolist.map(item => (
              <p key={ item.proid }>{ item.proname }</p>
            ))
          }
        </div>
      </div>
    )
  }
}

export default Com;

以上是关于react状态管理器的主要内容,如果未能解决你的问题,请参考以下文章

react状态管理器之mobx

react监听仓库数据变化

[react] 什么时候使用状态管理器?

[react] 状态管理器它精髓是什么?

react-redux状态管理器

React-5-状态管理器Redux