title: 使用 Redux

在 Taro 中可以自由地使用 React 生态中非常流行的数据流管理工具 Redux 来解决复杂项目的数据管理问题。而为了更方便地使用 Redux ,Taro 提供了与 react-redux API 几乎一致的包 @tarojs/redux 来让开发人员获得更加良好的开发体验。

下文中示例代码均在 taro-redux-sample

首先请安装 redux@tarojs/redux@tarojs/redux-h5,以及一些需要用到的 redux 中间件

  1. $ yarn add redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger
  2. # 或者使用 npm
  3. $ npm install --save redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger

随后可以在项目 src 目录下新增一个 store 目录,在目录下增加 index.js 文件用来配置 store,按自己喜好设置 redux 的中间件,例如下面例子中使用 redux-thunkredux-logger 这两个中间件

  1. // src/store/index.js
  2. import { createStore, applyMiddleware } from 'redux'
  3. import thunkMiddleware from 'redux-thunk'
  4. import { createLogger } from 'redux-logger'
  5. import rootReducer from '../reducers'
  6. const middlewares = [
  7. thunkMiddleware,
  8. createLogger()
  9. ]
  10. export default function configStore () {
  11. const store = createStore(rootReducer, applyMiddleware(...middlewares))
  12. return store
  13. }

接下来在项目入口文件 app.js 中使用 @tarojs/redux 中提供的 Provider 组件将前面写好的 store 接入应用中

  1. // src/app.js
  2. import Taro, { Component } from '@tarojs/taro'
  3. import { Provider } from '@tarojs/redux'
  4. import configStore from './store'
  5. import Index from './pages/index'
  6. import './app.scss'
  7. const store = configStore()
  8. class App extends Component {
  9. config = {
  10. pages: [
  11. 'pages/index/index'
  12. ],
  13. window: {
  14. navigationBarTitleText: 'Test'
  15. }
  16. }
  17. render() {
  18. return (
  19. <Provider store={store}>
  20. <Index />
  21. </Provider>
  22. )
  23. }
  24. }
  25. Taro.render(<App />, document.getElementById('app'))

然后就可以开始使用了。如 redux 推荐的那样,可以增加

  • constants 目录,用来放置所有的 action type 常量
  • actions 目录,用来放置所有的 actions
  • reducers 目录,用来放置所有的 reducers

例如我们要开发一个简单的加、减计数器功能

新增 action type

  1. // src/constants/counter.js
  2. export const ADD = 'ADD'
  3. export const MINUS = 'MINUS'

新增 reducer 处理

  1. // src/reducers/counter.js
  2. import { ADD, MINUS } from '../constants/counter'
  3. const INITIAL_STATE = {
  4. num: 0
  5. }
  6. export default function counter (state = INITIAL_STATE, action) {
  7. switch (action.type) {
  8. case ADD:
  9. return {
  10. ...state,
  11. num: state.num + 1
  12. }
  13. case MINUS:
  14. return {
  15. ...state,
  16. num: state.num - 1
  17. }
  18. default:
  19. return state
  20. }
  21. }
  1. // src/reducers/index.js
  2. import { combineReducers } from 'redux'
  3. import counter from './counter'
  4. export default combineReducers({
  5. counter
  6. })

新增 action 处理

  1. // src/actions/counter.js
  2. import {
  3. ADD,
  4. MINUS
  5. } from '../constants/counter'
  6. export const add = () => {
  7. return {
  8. type: ADD
  9. }
  10. }
  11. export const minus = () => {
  12. return {
  13. type: MINUS
  14. }
  15. }
  16. // 异步的 action
  17. export function asyncAdd () {
  18. return dispatch => {
  19. setTimeout(() => {
  20. dispatch(add())
  21. }, 2000)
  22. }
  23. }

最后,我们可以在页面(或者组件)中进行使用,我们将通过 tarojs/redux 提供的 connect 方法将 redux 与我们的页面进行连接

  1. // src/pages/index/index.js
  2. import Taro, { Component } from '@tarojs/taro'
  3. import { View, Text } from '@tarojs/components'
  4. import { connect } from '@tarojs/redux'
  5. import './index.scss'
  6. import { add, minus, asyncAdd } from '../../actions/counter'
  7. @connect(({ counter }) => ({
  8. counter
  9. }), (dispatch) => ({
  10. add () {
  11. dispatch(add())
  12. },
  13. dec () {
  14. dispatch(minus())
  15. },
  16. asyncAdd () {
  17. dispatch(asyncAdd())
  18. }
  19. }))
  20. class Index extends Component {
  21. config = {
  22. navigationBarTitleText: '首页'
  23. }
  24. render () {
  25. return (
  26. <View className='todo'>
  27. <Button className='add_btn' onClick={this.props.add}>+</Button>
  28. <Button className='dec_btn' onClick={this.props.dec}>-</Button>
  29. <Button className='dec_btn' onClick={this.props.asyncAdd}>async</Button>
  30. <View>{this.props.counter.num}</View>
  31. </View>
  32. )
  33. }
  34. }
  35. export default Index

connect 方法接受两个参数 mapStateToPropsmapDispatchToProps

  • mapStateToProps,函数类型,接受最新的 state 作为参数,用于将 state 映射到组件的 props
  • mapDispatchToProps,函数类型,接收 dispatch() 方法并返回期望注入到展示组件的 props 中的回调方法