使用 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 将不会重新渲染我们的组件。