【初识React】 - redux + redux-react

69 阅读2分钟

redux 相关安装

  • yarn add redux
  • yarn add react-redux react对redux的友好支持
  • yarn add redux-thunk redux 异步中间件
  • yarn add redux-logger redux 操作日志

redux 组成

  • state 存储属性
  • action action对象 - 负责告知store要执行的动作
  • reducer 根据action动作,进行相应处理,并将处理后的数据返回store

项目结构

- src
    - components UI组件
        - counter
            - index.js
    - pages 页面
        - counter
            - index.js
    - store 仓库
        - action
            - xxxaction.js
        - reducer
            - xxxreducer.js
            - index.js
        - index.js
     - App.js 

示例【1】 action创建函数

// store/action/counter.js
// 定义action type 对应枚举值, ts友好
export const actionType = {
    ADD: 'ADD'
}

// action 创建函数 - 通过action创建函数 返回一个action对象
// 亦可省略action创建函数。 直接使用action对象
export const addCount = (count) => {
    return {
        type: actionType.ADD,
        count
    }
}

示例【2】 单个reducer

// store/reducer/counter.js
import { actionType } from '../action/counter.js'
const counter = (state = 0, action) => {
    switch(action.type){
        case actionType.ADD:
            return state + action.count;
        default:
            return state;
    }
}
export default counter

示例【3】 合并多个reducer并输出

// store/reducer/index.js
import { combineReducers } from 'redux'; // combineReducers 合并多个reducer
import counterReducer from './counter.js'
export default combineReducers({
    // counterReducer, // 方式1 
    counter: counterReducer, // 方式2 别名
})

示例【4】 将reducer挂载到store仓库

// store/index.js
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'
import RootReducers from './reducers/index.js'

export default createStore(RootReducers, applyMiddleware(
  thunkMiddleware, // 异步支持
  createLogger(), // 操作日志
))

上述4个示例通过redux依赖帮助我们建立了store,接下来需要用到react-redux在UI组件或页面中进行使用

react-redux 示例【1】

// App.js
// Provider 容器 - 被该容器包裹的组件或页面 才可以使用react-redux相关的功能
// 且被 Provider 容器包裹后的组件或页面 其 子孙组件同样可使用react-redux
import { Provider } from 'react-redux'  
import store from './store' // store 仓库
import counterPage from './pages/counter/index' // 页面

function App() {
    return (
        <Provider store={store}>
           <div className="App">
               <counterPage />
           </div>
        </Provider>
    );
}

react-redux 示例【2】

// pages/counter/index.js
import Counter from '../../components/counter/index'

const counterPage = () => {
    return (
        <div className="counter-page">
            页面其他内容 ...
            <Counter />
            页面其他内容 ...
        </div>
    );
}

export default counterPage

react-redux 示例【3】

 // components/counter/index.js
 import { connect } from 'react-redux'
 import { addCount } from '../../store/action/counter.js'
 
 const Counter = (props) => {
     
     // 通过connect后 该组件props 中便具备了 mapStateToProps 及 mapDispatchToProps中的属性及方法
     const { count, add } = props;
     return (
         <div className="counter">
            <span>{count}</span>
            <button onClick={() => add(1)}>增加</button>
         </div>
     );
 }
 
 // mapStateToProps 是一个映射关系, 即 将定义的某个key的值 与 store中的某个属性进行映射
 const mapStateToProps = (state) => {
     return {
         count: state.counter, // combineReducer时使用了别名 即 counter
     }
 }
 
 // dispatch 接收一个action对象
 // 我们通过action创建函数 生成一个action对象 并提供给dispatch
 const mapDispatchToProps = (dispatch) => {
     return {
         add: (val) => dispath(addCount(val))
     }
 }
 
 export defalut connect(mapStateToProps, mapDispatchToProps)(Counter)

到此 redux 及 react-redux 的基本使用变完成了。 小白初学,如果上述有问题欢迎留言指证,您的一次指证或许能帮助更多的人少走很多的弯路 哈哈~

注: 上面有引入thunk,但示例中并未有异步的例子

另外 附上 redux 的中文文档 里面有更详细的介绍redux 的各种使用