使用 React Redux 的 Hello World
本指南假设你已经安装了 react
,redux
,react-router
和 react-redux
并配置了 react
,redux
和 react-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 获取数据,并有一个按钮,点击该按钮更新商店中的数据。
应用结构
我们的 rootReducer
有 user
减速机
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
方法有三个参数
mapStateToProps , mapDispatchToProps 和 Component 本身。
connect( mapStateToProps, mapDispatchToProps )(Component)
让我们添加连接到我们的组件 UserComponent 以及 mapStateToProps 和 mapDispatchToProps
而且我们还要更新我们的 changeUserDetails 函数,所以当调用它时,它将根据我们的 reducers
的 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 :这允许我们将
dispatch actions
发送到我们组件中的所有 reducers …(可以是任何组件),并且基于动作的type
,我们的 userReducer 将启动并返回具有更新数据的新状态。 -
ConnectedUserComponent :最后,我们使用
connect
方法将我们的组件连接到商店,方法是将所有参数和exported
传递给连接的组件。 -
我们还更新了我们的 changeUserDetails 函数,在 props 上调用
method
并传入数据。然后props
将调用我们调用的方法调度到所有 reducers。
注意:
- 如果我们不从 reducer 返回一个新状态,
react-redux
将不会重新渲染我们的组件。