使用 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 減速機

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 函式,所以當呼叫它時,它將根據我們的 reducersaction,並根據我們的 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 :這允許我們將 dispatch actions 傳送到我們元件中的所有 reducers …(可以是任何元件),並且基於動作的 type,我們的 userReducer 將啟動並返回具有更新資料的新狀態。

  • ConnectedUserComponent :最後,我們使用 connect 方法將我們的元件連線到商店,方法是將所有引數和 exported 傳遞給連線的元件。

  • 我們還更新了我們的 changeUserDetails 函式,在 props 上呼叫 method 並傳入資料。然後 props 將呼叫我們呼叫的方法排程到所有 reducers。

注意:

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