react-reduxreact-redux入門


備註

React Redux是一個為Redux提供React綁定的庫。

了解Redux存儲的React組件稱為“容器”,“智能組件”或“高階組件”(HOC)。要使用Redux,這些組件需要:

  • 訂閱商店以獲取Redux商店的更新
  • 派遣行動

手動執行此操作意味著在React容器中使用store.subscribestore.dispatch(action)

React Redux通過connect函數簡化了Redux存儲和React容器組件之間的綁定,該函數將Redux狀態屬性和Action創建者映射到組件的props。

connect是一個創建更高階組件的函數。 Connect接受3個函數( mapStateToPropsmapDispatchToPropsmergeProps )並返回一個容器組件,它包裝原始組件以使其成為“連接”組件:

import { connect } from 'react-redux';

const Customers = { ... };
const mapStateToProps = (state) => { ... }
const mapDispatchToProps = (dispatch) => { ... }

export default connect(mapStateToProps, mapDispatchToProps)(Customers);

有關完整示例,請參閱示例部分。

由於所有容器組件都需要訪問Redux存儲,因此推薦的方法是使用React Redux的特殊<Provider>組件,它將存儲傳遞給所有子組件(在內部使用React上下文)。

官方文檔: http//redux.js.org/docs/basics/UsageWithReact.html

GitHub回購: https//github.com/reactjs/react-redux

版本

發布日期
5.0.3 2017年2月23日
5.0.2 2017年1月11日
5.0.1 2016年12月14日
5.0.0 2016年12月14日
4.4.6 2016年11月14日
4.4.5 2016年4月14日
4.4.4 2016年4月13日
4.4.3 2016年4月12日
4.4.0 2016年2月6日
4.3.0 2016年2月5日
4.2.0 2016年2月1日
4.1.0 2016年1月28日
4.0.0 二零一五年十月十五日
3.0.0 2015年9月24日
2.0.0 2015年9月1日
1.0.0 2015年8月24日
0.5.0 2015年8月7日
0.1.0 2015年7月12日

完整的例子

假設我們有容器“CustomersContainer”,它將“Customers”啞組件連接到Redux商店。

在index.js中:

import { Component }, React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './redux/rootReducer';
import CustomersContainer from './containers/CustomersContainer';

let store = createStore(rootReducer);

render(
  <Provider store={store}>
    <CustomersContainer />
  </Provider>,
  document.getElementById('root')
);
 

在CustomersContainer中:

import React, { Component } from 'react';
import { connect } from 'react-redux';

// Import action creators
import { fetchCustomers } from '../redux/actions';

// Import dumb component
import Customers from '../components/Customers';

// ES6 class declaration
class CustomersContainer extends Component {
  componentWillMount() {
    // Action fetchCustomers mapped to prop fetchCustomers
    this.props.fetchCustomers();
  }

  render() {
    return <Customers customers={this.props.customers} />;
  }
}

function mapStateToProps(state) {
  return {
    customers: state.customers
  };
}

// Here we use the shorthand notation for mapDispatchToProps
// it can be used when the props and action creators have the same name 
const CustomersContainer = connect(mapStateToProps, { fetchCustomers })(CustomersContainer);

export default CustomersContainer;
 

使用React Redux的Hello World

本指南假設您已經安裝了reactreduxreact-routerreact-redux 並配置了reactreduxreact-router 。如果還沒有,請這樣做。

注意:雖然react-router 不依賴於react-redux ,但我們很可能會在反應應用程序中使用它來進行路由,這使我們很容易使用react-redux。


FILENAME: app.js

'use strict';

import React from 'react';
import { render } from 'react-dom';
import { Router, Route, Link, browserHistory, IndexRoute } from 'react-router';
import { Provider } from 'react-redux';
import store from './stores';

render(
  (
    <Provider store={ store }>
      <Router history={ browserHistory }>
        {/* all the routes here */}
      </Router>
    </Provider>
  ),
  document.getElementById('app')
);
 

這個文件對大多數人來說都是有意義的,我們在這裡做的是從./stores 獲取商店並使用react-redux 提供的高階組件Provider 將其傳遞給所有路由。

這使得商店在整個應用程序中都可用。


現在,讓我們考慮一下這種情況 。我們有一個組件UserComponent ,它從user reducer獲取數據,並有一個按鈕,當點擊它時更新商店中的數據。

應用結構

我們的rootReduceruser reducer

const rootReducer = combineReducers({
    user: userReducer,
})
export default rootReducer;
 

我們的userReducer 看起來像這樣

const default_state = {
  users: [],
  current_user: {
    name: 'John Doe',
    email: 'john.doe@gmail.com',
    gender: 'Male'
  },
  etc: {}
};

function userReducer( state=default_state, action ) {

  if ( action.type === "UPDATE_CURRENT_USER_DATA" ) {
    return Object.assign( {}, state, { current_user: Object.assign( {}, state.current_user, { [action.payload.field]: action.payload.value } ) } );
  }
  else {
    return state;
  }

}

export default userReducer;
 

我們的actions 文件看起來像這樣

export function updateCurrentUserData( data ) {
  return {
    type: "UPDATE_CURRENT_USER_DATA",
    payload: data
  }
}
 

最後,讓我們在我們的組件上工作

FILENAME: UserComponent.js

'use strict';

import React from 'react';
import { connect } from 'react-redux';
import * as Action from './actions';

let UserComponent = (props) => {

  let changeUserDetails = (field, value) => {
    // do nothing
  }

  return(
    <div>
      <h1>Hello { props.current_user.name }</h1>
      <p>Your email address is { props.current_user.email }</p>
      <div style={{ marginTop: 30 }}>
        <button onClick={ () => { changeUserDetails('name', 'Jame Smith') } }>Change Name</button>
        <button onClick={ () => { changeUserDetails('email', 'jane@gmail.com') } }>Change Email Address</button>
      </div>
    </div>
  )

}

export default UserComponent;
 

當然這不起作用 ,因為我們尚未將它連接到商店。

如果你想知道,這是一個無狀態的功能組件 ,因為我們使用的是redux ,我們並不需要組件的內部狀態,這是使用它的正確時間。

react-redux 提供的connect 方法有三個參數

mapStateToPropsmapDispatchToPropsComponent本身。

connect( mapStateToProps, mapDispatchToProps )(Component)


讓我們添加連接到我們的組件UserComponent以及mapStateToPropsmapDispatchToProps

我們還要更新我們的changeUserDetails函數,因此在調用時,它會向我們的reducers dispatch 一個action ,並根據我們的reducer將啟動並對商店進行更改的動作類型,並且一旦商店更新了react-redux 將重新啟動使用新數據渲染我們的組件。

聽起來很複雜?它真的不是。

我們的UserComponent.js 看起來像

'use strict';

import React from 'react';
import { connect } from 'react-redux';
import * as Action from './actions';

const mapStateToProps = ( state, ownProps ) => {
  return {
    current_user: state.user.current_user,
  }
}

const mapDispatchToProps = ( dispatch, ownProps ) => {
  return {
    updateCurrentUserData: (payload) => dispatch( Action.updateCurrentUserData(payload) ),
  }
}


let UserComponent = (props) => {

  let changeUserDetails = (field, value) => {
    props.updateCurrentUserData({ field: field, value: value });
  }

  return(
    <div>
      <h1>Hello { props.current_user.name }</h1>
      <p>Your email address is { props.current_user.email }</p>
      <div style={{ marginTop: 30 }}>
        <button onClick={ () => { changeUserDetails('name', 'Jame Smith') } }>Change Name</button>
        <button onClick={ () => { changeUserDetails('email', 'jane@gmail.com') } }>Change Email Address</button>
      </div>
    </div>
  )

}

const ConnectedUserComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(UserComponent)

export default ConnectedUserComponent;
 

我們在這裡做了什麼

  • mapStateToProps:這使我們能夠得到存儲和數據發生變化的數據,我們的組件將被重新渲染與新的數據。

    我們的組件只會在我們的組件請求更改商店的數據時重新呈現,而不會在商店中的任何其他數據更改時重新呈現。

  • mapDispatchToProps :這允許我們從我們的組件向所有reducers dispatch actions ..(可以是任何組件),並且根據動作type ,我們的userReducer將啟動並返回具有更新數據的新狀態。

  • ConnectedUserComponent :最後,我們使用connect 方法將組件連接到商店,方法是傳遞所有參數並exported 連接的組件。

  • 我們還更新了我們的changeUserDetails函數來調用props上的method 並傳入數據。然後, props 會調度我們調用的方法給所有reducers。


注意:

  • 如果我們不從reducer返回一個新狀態, react-redux 不會重新渲染我們的組件。

安裝或設置

直接使用redux with react 可能看起來有點困難。對於存儲更改時要更新的每個component ,您必須將該組件訂閱到redux store

React Redux負責處理所有這些,並且可以很容易地編寫可以從redux store 請求所需數據的組件,並且只有在這些數據發生變化時才會收到通知。這使我們能夠編寫真正有效的組件。

要安裝react-redux 您只需運行此npm 命令即可

npm install --save react-redux
 

而且你已經完成了。


注意: React Redux依賴於

  • React(版本0.14或更高版本)和
  • 終極版