taro使用 Redux官方教程


請使用taro的1.2.20版本

 

在 Taro 中可以自由地使用 React 生態中非常流行的數據流管理工具 Redux 來解決復雜項目的數據管理問題。而為了更方便地使用 Redux ,Taro 提供了與 react-redux API 幾乎一致的包 @tarojs/redux 來讓開發人員獲得更加良好的開發體驗。

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

首先請安裝 redux 、 @tarojs/redux 和 @tarojs/redux-h5,以及一些需要用到的 redux 中間件

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

 

隨后可以在項目 src 目錄下新增一個 store 目錄,在目錄下增加 index.js 文件用來配置 store,按自己喜好設置 redux 的中間件,例如下面例子中使用 redux-thunk 和 redux-logger 這兩個中間件

// src/store/index.js
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'
import rootReducer from '../reducers'
 
const middlewares = [
thunkMiddleware,
createLogger()
]
 
export default function configStore () {
const store = createStore(rootReducer, applyMiddleware(...middlewares))
return store
}

 

接下來在項目入口文件 app.js 中使用 @tarojs/redux 中提供的 Provider 組件將前面寫好的 store 接入應用中

// src/app.js
import Taro, { Component } from '@tarojs/taro'
import { Provider } from '@tarojs/redux'
 
import configStore from './store'
import Index from './pages/index'
 
import './app.scss'
 
const store = configStore()
 
class App extends Component {
render() {
return (
<Provider store={store}>
{this.props.children}
</Provider>
)
}
}
 
Taro.render(<App />, document.getElementById('app'))

 

 

然后就可以開始使用了。如 redux 推薦的那樣,可以增加

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

例如我們要開發一個簡單的加、減計數器功能

新增 action type

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

新增 reducer 處理

// src/reducers/counter.js
import { ADD, MINUS } from '../constants/counter'
 
const INITIAL_STATE = {
num: 0
}
 
export default function counter (state = INITIAL_STATE, action) {
switch (action.type) {
case ADD:
return {
...state,
num: state.num + 1
}
case MINUS:
return {
...state,
num: state.num - 1
}
default:
return state
}
}

 

// src/reducers/index.js
import { combineReducers } from 'redux'
import counter from './counter'
 
export default combineReducers({
counter
})

 

 

新增 action 處理

// src/actions/counter.js
import {
ADD,
MINUS
} from '../constants/counter'
 
export const add = () => {
return {
type: ADD
}
}
export const minus = () => {
return {
type: MINUS
}
}
 
// 異步的 action
export function asyncAdd () {
return dispatch => {
setTimeout(() => {
dispatch(add())
}, 2000)
}
}

 

 

最后,我們可以在頁面(或者組件)中進行使用,我們將通過 tarojs/redux 提供的 connect 方法將 redux 與我們的頁面進行連接

// src/pages/index/index.js
import Taro, { Component } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import { connect } from '@tarojs/redux'
import './index.scss'
 
import { add, minus, asyncAdd } from '../../actions/counter'
 
@connect(({ counter }) => ({
counter
}), (dispatch) => ({
add () {
dispatch(add())
},
dec () {
dispatch(minus())
},
asyncAdd () {
dispatch(asyncAdd())
}
}))
class Index extends Component {
config = {
navigationBarTitleText: '首頁'
}
 
render () {
return (
<View className='todo'>
<Button className='add_btn' onClick={this.props.add}>+</Button>
<Button className='dec_btn' onClick={this.props.dec}>-</Button>
<Button className='dec_btn' onClick={this.props.asyncAdd}>async</Button>
<View>{this.props.counter.num}</View>
</View>
)
}
}
 
export default Index

 

connect 方法接受兩個參數 mapStateToProps 與 mapDispatchToProps

  • mapStateToProps,函數類型,接受最新的 state 作為參數,用於將 state 映射到組件的 props
  • mapDispatchToProps,函數類型,接收 dispatch() 方法並返回期望注入到展示組件的 props 中的回調方法

#Hooks

#在 Redux 中使用 Hooks

使用 hooks 的基本設置和使用 connect 的設置是一樣的,你需要設置你的 store,並把你的應用放在 Provider 組件中。

const store = configreStore(rootReducer)
 
class App extends Components {
render () {
return (
<Provider store={store}>
<Index />
</Provider>
)
}
}

 

在這樣的情況下,你就可以使用 taro-redux 提供的 Hooks API 在函數式組件中使用。

#useSelector

const result : any = useSelector(selector : Function, equalityFn? : Function)

useSelector 允許你使用 selector 函數從一個 Redux Store 中獲取數據。

Selector 函數大致相當於 connect 函數的 mapStateToProps 參數。Selector 會在組件每次渲染時調用。useSelector 同樣會訂閱 Redux store,在 Redux action 被 dispatch 時調用。

但 useSelector 還是和 mapStateToProps 有一些不同:

  • 不像 mapStateToProps 只返回對象一樣,Selector 可能會返回任何值。
  • 當一個 action dispatch 時,useSelector 會把 selector 的前后返回值做一次淺對比,如果不同,組件會強制更新。
  • Selector 函數不接受 ownProps 參數。但 selector 可以通過閉包訪問函數式組件傳遞下來的 props。

#使用案例

基本使用:

import Taro, { Components } from '@tarojs/taro'
import { useSelector } from '@tarojs/redux'
 
export const CounterComponent = () => {
const counter = useSelector(state => state.counter)
return <View>{counter}</View>
}

 

使用閉包決定如何 select 數據:

export const TodoListItem = props => {
const todo = useSelector(state => state.todos[props.id])
return <View>{todo.text}</View>
}

 

 

#進階使用

你還可以訪問 react-redux 文檔 了解如何使用 reselect 緩存 selector。

#useDispatch

const dispatch = useDispatch()

這個 Hook 返回 Redux store 的 dispatch 引用。你可以使用它來 dispatch actions。

#使用案例

import Taro, { Components } from '@tarojs/taro'
import { useDispatch } from '@tarojs/redux'
 
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
 
return (
<View>
<Text>{value}</Text>
<Button onClick={() => dispatch({ type: 'increment-counter' })}>
Increment counter
</Button>
</View>
)
}

 

當我們使用 dispatch 傳遞回調到一個子組件時,推薦使用 useCallback 把回調緩存起來,因為組件可能因為引用改變而重新渲染。

// CounterComponent.js
export const CounterComponent = ({ value }) => {
const dispatch = useDispatch()
const incrementCounter = useCallback(
() => dispatch({ type: 'increment-counter' }),
[dispatch]
)
 
return (
<View>
<Text>{value}</Text>
<MyIncrementButton onIncrement={incrementCounter} />
</View>
)
}
 
// IncrementButton.js
const MyIncrementButton = ({ onIncrement }) => (
<Button onClick={onIncrement}>Increment counter</Button>
)
 
export default Taro.memo(MyIncrementButton)

 

#useStore

const store = useStore()

 

useStore 返回一個 store 引用和 Provider 組件引用完全一致。

這個 hook 可能並不經常使用。useSelector 大部分情況是你的第一選擇,如果需要替換 reducers 的情況下可能會使用到這個 API。

#使用案例

import Taro, { Components } from '@tarojs/taro'
import { useStore } from '@tarojs/redux'
 
export const CounterComponent = ({ value }) => {
const store = useStore()
 
// EXAMPLE ONLY! Do not do this in a real app.
// The component will not automatically update if the store state changes
return <div>{store.getState()}</div>
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM