依照慣例,開頭先放出redux中文文檔地址
前文講了redux
的基礎概念,這次學習一下redux
和react
的結合使用
React-Redux
說到redux
在react
中的使用,肯定繞不開react-redux
這個庫。首先聲明,在react
中使用redux
并非一定要用react-redux
,同樣的redux
也不是只能為react
服務,它同樣也支持vue
、Angular
、純JS
等等。這里使用react-redux
更多的是考慮這已經算react
生態圈的最佳實踐了。
connect()
react-redux
提供了connect()
方法。
連接 React 組件
與 Redux store
。
連接操作不會改變原來的組件,返回一個新的已與Redux store
連接的組件。
調用方法: connect([mapStateToProps], [mapDispatchToProps], [mergeProps],[options])
講解一下參數,基本都是顧名思義:
[mapStateToProps(state, {ownProps})](Function): 一個函數,返回一個對象,把store中的state傳到UI組件上,也可以把容器組件自己的props傳遞過去
[mapDispatchToProps(dispatch, {ownProps}): dispatchProps)](Object or Function): 一個函數或對象,定義UI組件上的props和需要觸發的Action之間的映射關系
<Provider>標簽
定義完connect()
方法,想要生成容器組件
還需把state
傳遞給容器組件
(回顧一下上面的邏輯,UI組件
是我們自定義的,通過react-redux
提供的connect()
方法,我們已經把store
中的state
傳給了UI組件
的props
,UI組件
中需要觸發store
中state
變化的Action
函數也已經傳入,但是我們只建立了這種連接關系,容器組件
的state
還沒有定義)。<Provider>
標簽作用就是通過react
組件的context
把store
中的state
直接傳入。
例子:
ReactDOM.render(
<Provider store={store}>
<MyRootComponent />
</Provider>,
rootElement
)
至此,如果不考慮異步場景,我們應該已經可以在react
項目中使用redux
了
下面在create-react-app
腳手架上開始寫一個簡單的小例子:
- 初始化一個
react
項目,原始項目應該包含一個app首頁
react-app - 在此項目基礎上安裝
redux
/react-redux
/react-router
等包 - 創建state相關目錄(此處
sagas
非必要,僅在后文處理異步場景示例中使用到)
image.png - 在
actions
中創建action
例如:
在function mark({ payload: id }) { return { type: 'MARK ITEM', payload: id }; }
reducers
中創建reduce
例如:
合并const initialUi = { backgroundColor: false }; function markItem (state = initialUi, action) { let backgroundColor = state.backgroundColor; if (action.type === 'MARK ITEM') { backgroundColor = !backgroundColor; return backgroundColor; } return backgroundColor; } function ui (state = initialUi, action) { return { backgroundColor: markItem(state, action) } } export default ui;
reducer
在import { combineReducers } from 'redux'; const reducer = combineReducers({ ui }); export default reducer;
store
中創建store
在import { createStore, applyMiddleware } from 'redux'; const store = createStore( reducer ); export default store;
container
組件中把組件屬性和store
相連
在import React, { Component } from 'react'; import { connect } from 'react-redux'; import { mark } from '../state/actions/ui'; class example extends Component { constructor() { super(); } render () { console.log(this.props) return ( <div> { this.props.ui.backgroundColor } <ul> <li key={0} onClick={() => this.props.markItem(0)}>0</li> <li key={1} onClick={() => this.props.markItem(1)}>1</li> <li key={2} onClick={() => this.props.markItem(2)}>2</li> </ul> </div> ); } } const mapStateToProps = (state) => { return { ui: state.ui } }; const mapDispatchToProps = (dispatch) => { return { markItem: id => { dispatch(mark({ payload: id })); } }; }; const Example = connect( mapStateToProps, mapDispatchToProps )(example);
App
中添加組件,同時引入react-router
在class App extends Component { render() { return ( <div> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <h1 className="App-title">Welcome to React</h1> </header> <Router> ... <Route path="/example" component={Example}/> </div> </Router> </div> ); } }
index.js
中通過<Provider>
組件傳入store
... import { Provider } from 'react-redux'; import store from './state/store/store'; import App from './App'; ... ReactDOM.render( <Provider store={ store }> <App /> </Provider>, document.getElementById('root') );
初始狀態.png
點一下狀態發生改變.png
(這里介紹一個調試redux
的小工具Redux DevTools,是一個中間件,使用方式可以自己看鏈接)
這就完成了把目前所有redux
和react
相關內容串聯起來的小例子
(未完待續。。。)