Redux在React中的使用

redux

Redux是一个数据状态管理插件,当使用React或是vue开发组件化的SPA程序时,组件之间共享信息是一个非常大的问题。例如,用户登陆之后客户端会存储用户信息(ID,头像等),而系统的很多组件都会用到这些信息,当使用这些信息的时候,每次都重新获取一遍,这样会非常的麻烦,因此每个系统都需要一个管理多组件使用的公共信息的功能,这就是redux的作用。

简单使用

import { createStore } from 'redux'
  • 第一步:定义计算规则,即reducer
function counter(state = 0, action) {
    switch (action.type) {
        case 'INCREMENT': 
            return state + 1
        case 'DECREMENT': 
            return state - 1
        default: 
            return state
    }
}
  • 第二步:根据计算规则生成store
let store = creatStore(counter);
  • 第三步:定义数据(state)变化之后的派发规则
store.subscribe(() => {
    console.log('fn1 -> current state', store.getState())
})
store.subscribe(() => {
    console.log('fn2 -> current state', store.getState())
})
  • 第四步:触发数据变化
store.dispatch({
    type: 'INCREMENT',
})

在React中使用

redux经常和react搭配使用,使用React开发系统,绝大部分都需要结合Redux来使用,下面介绍一下如何在React中使用redux.

前四步和之前的差不多,但是要注意结构的拆分。

导入依赖

npm install redux --save
npm install react-redux --save

文件目录结构

  • reducers

    • index.js

      Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大。若把传入Reducer的Action改变为State的属性,属性间没有关联,我们就可以把Reducer函数拆分,不同函数负责处理不同属性,最终用combineReducers合并成一个大的Reducer即可。

      import { combineReducers } from 'redux';
      import userInfo from './userInfo'
      const rootRuducer =  combineReducers({
          userInfo,
          //userInfo是State的一个属性,也是一个action方法,同名。若不想同名,可写成a: doSomethingWithA的形式(a是State的属性)。
      })
      export default rootRuducer;
    • userInfo.js

      import * as actionTypes from '../constants/userInfo';
      const initState = {}
      export default function userInfo (state = initState, action) {
          switch(action.type) {
              case actionTypes.UPDATE_CITYNAME:
                  return action.data
              default:
                  return state
          }
      }
  • actions

    • userInfo.js

      import * as actionTypes from '../constants/userInfo';
      export function updateCityName(data) {
          return {
              type: actionTypes.UPDATE_CITYNAME,
              data,
          }
      }
      export function XXX(){
          return {}
      }
  • constants

    • userInfo.js

      扫描二维码关注公众号,回复: 4506524 查看本文章

      被多个地方引用,这样可以方便修改

      export const UPDATE_CITYNAME = 'UPDATE_CITYNAME';
  • store

    • configureStore.js

      导出创建store的函数

      import { createStore } from 'redux';
      import rootRuducer from '../reducers';
      
      export default function configureStore(initState) {
          const store = createStore(rootRuducer, initState, 
              window.devToolsExtension ? window.devToolsExtension() : undefined
              );
          return store;
      }
  • containers

    存放页面的文件夹

    • index.js

      mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。

      mapStateToProps的第一个参数总是state对象,还可以使用第二个参数,代表容器组件的props对象。

      mapDispatchToPropsconnect函数的第二个参数,用来建立 UI 组件的参数到store.dispatch方法的映射。也就是说,它定义了哪些用户的操作应该当作 Action,传给 Store。它可以是一个函数,也可以是一个对象。

      如果mapDispatchToProps是一个函数,会得到dispatchownProps(容器组件的props对象)两个参数,返回一个对象,该对象的每个键值对都是一个映射,定义了 UI 组件的参数怎样发出 Action。

      bindActionCreators(actionCreators, dispatch)把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。同时使用 dispatch 对每个 action creator 进行包装,以便可以直接调用它们。

      一般情况下你可以直接在 Store 实例上调用 dispatch。如果你在 React 中使用 Redux,react-redux 会提供 dispatch 函数让你直接调用它 。

      惟一会使用到 bindActionCreators 的场景是当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把 dispatch 或 Redux store 传给它。

      import React from 'react';
      import { bindActionCreators } from 'redux';
      import { connect } from 'react-redux';
      import * as userInfoActionsFromOtherFile from '../actions/userInfo.js';
      class App extends React.Component {
          constructor(props) {
              super(props);
              this.state = {
                  initDone: false
              }
          }
          componentDidMount() {
              this.setState({
                  initDone: true,
              })
          }
          render() {
              return (
                  <div>
                      {this.state.initDone ? this.props.children : 'loadding...'}
                  </div>
              )
          }
      }
      function mapStateToProps(state) {
          return {
              userInfo: state.userinfo,
          }
      }
      function mapDispatchToProps(dispatch) {
          return {
              userInfoAction: bindActionCreators(userInfoActionsFromOtherFile, dispatch),
          }
      }
      export default connect(
          mapStateToProps,
          mapDispatchToProps // 定义了哪些用户的操作应该当作 Action,传给 Store
      )(App);
  • index.js

    React-Redux 提供Provider组件,可以让容器组件拿到state。所以在入口文件夹中,先创建store,然后再把 包裹一层。

    import React from 'react';
    import ReactDOM from 'react-dom';
    // import { render } from 'react-dom';
    import { Provider } from 'react-redux';
    import configureStore from './store/configureStore';
    import App from './containers//index';
    
    const store = configureStore();
    
    ReactDOM.render(
        <Provider store={store}>
            <App />
        </Provider>,
        document.getElementById('root')
    );

猜你喜欢

转载自www.cnblogs.com/xiongxiaolong/p/10121094.html