React 和 Redux:React 和 Redux 入门
React 是提供数据的视图库,能以高效、可预测的方式渲染视图。Redux 是状态管理框架,可用于简化 APP 应用状态的管理。
在 React Redux app 应用中,通常可创建单一的 Redux store 来管理整个应用的状态。React 组件仅订阅 store 中与其角色相关的数据,你可直接从 React 组件中分发 actions 以触发 store 对象的更新。
Redux 没有内置的 React,需要安装react-redux
包,通过这个方式把 Redux 的state
和dispatch
作为props
传给组件。
class DisplayMessages extends React.Component {
constructor(props){
super(props);
this.state = {
input: "",
messages: []
}
}
render() {
return <div />
}
};
React 和 Redux:首先在本地管理状态
class DisplayMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
messages: []
};
this.handleChange = this.handleChange.bind(this);
this.submitMessage = this.submitMessage.bind(this);
}
handleChange(event){
this.setState({
input: event.target.value
})
}
submitMessage(){
const msg =this.state.input.trim()!==''?[...this.state.messages,this.state.input]:[...this.state.messages];
this.setState({
messages: msg,
input: ''
})
}
render() {
const items=this.state.messages.map(i => <li key={i+1}>{i}</li>);
return (
<div>
<h2>键入新 Message</h2>
<input
onChange={this.handleChange}
value={this.state.input} />
<button onClick={this.submitMessage}>Add message</button>
<ul>
{items}
</ul>
</div>
);
}
};
React 和 Redux:提取状态逻辑给 Redux
const ADD = 'ADD';
const addMessage = (message) => {
return {
type: ADD,
message: message
}
};
const messageReducer = (state=[],action) => {
switch(action.type){
case ADD:
return [...state,action.message];
default:
return state;
}
};
const store = Redux.createStore(messageReducer);
React 和 Redux:使用 Provider 连接 Redux 和 React
React Redux 提供的 API 有两个关键的功能:Provider
和connect
。
Provider
是 React Redux 包装 React 应用的 wrapper 组件,它允许你访问整个组件树中的 Redux store
及dispatch
(分发)方法。Provider
需要两个 props:Redux store 和 APP 应用的子组件。用于 APP 组件的Provider
可这样定义:
<Provider store={store}>
<App/>
</Provider>
// Redux 代码:
const ADD = 'ADD';
const addMessage = (message) => {
return {
type: ADD,
message
}
};
const messageReducer = (state = [], action) => {
switch (action.type) {
case ADD:
return [
...state,
action.message
];
default:
return state;
}
};
const store = Redux.createStore(messageReducer);
// React 代码:
class DisplayMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
input: '',
messages: []
}
this.handleChange = this.handleChange.bind(this);
this.submitMessage = this.submitMessage.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
submitMessage() {
const currentMessage = this.state.input;
this.setState({
input: '',
messages: this.state.messages.concat(currentMessage)
});
}
render() {
return (
<div>
<h2>Type in a new Message:</h2>
<input
value={this.state.input}
onChange={this.handleChange}/><br/>
<button onClick={this.submitMessage}>Submit</button>
<ul>
{this.state.messages.map( (message, idx) => {
return (
<li key={idx}>{message}</li>
)
})
}
</ul>
</div>
);
}
};
const Provider = ReactRedux.Provider;
class AppWrapper extends React.Component {
render(){
return (
<Provider store={store}>
<DisplayMessages />
</Provider>
);
}
};
注意: React Redux 在此可作全局变量,因此你可通过点号表示法访问 Provider。可以把Provider
设置为常量,便于你在AppWrapper
渲染方法中使用。
React 和 Redux:映射 State 到 Props
Provider
可向 React 组件提供state
和dispatch
,但你必须确切地指定所需要的 state 和 actions,以确保每个组件只能访问所需的 state。完成这个任务,你需要创建两个函数:mapStateToProps()
、mapDispatchToProps()
。
const state = [];
const mapStateToProps = (state) => {
return {
messages: state
}
};
注意: 在幕后,React Redux 用store.subscribe()
方法来实现mapStateToProps()
。
React 和 Redux:映射 Dispatch 到 Props
mapDispatchToProps()
函数可为 React 组件提供特定的创建 action 的函数,以便组件可 dispatch actions,从而更改 Redux store 中的数据。它返回一个对象,把 dispatch actions 映射到属性名上,该属性名成为props
。
然而,每个属性都返回一个用 action creator 及与 action 相关的所有数据调用dispatch
的函数,而不是返回state
的一部分。你可以访问dispatch
,因为在定义函数时,我们以参数形式把它传入mapDispatchToProps()
了,这跟state
传入mapDispatchToProps()
是一样的。
在幕后,React Redux 用 Redux 的store.dispatch()
来管理这些含mapDispatchToProps()
的dispatches,这跟它使用store.subscribe()
来订阅映射到state的组件的方式类似。
例如,创建 action 的函数loginUser()
把username
作为 action payload,mapDispatchToProps()
返回给创建 action 的函数的对象如下:
{
submitLoginUser: function(username) {
dispatch(loginUser(username));
}
}
const addMessage = (message) => {
return {
type: 'ADD',
message: message
}
};
const mapDispatchToProps = (dispatch) => {
return {
submitNewMessage(message){
dispatch(addMessage(message))
}
}
}
React 和 Redux:连接 Redux 和 React
既然写了mapStateToProps()
、mapDispatchToProps()
两个函数,现在你可以用它们来把state
和dispatch
映射到 React 组件的props
了。
React Redux 的connect
方法可以完成这个任务。此方法有mapStateToProps()
、mapDispatchToProps()
两个可选参数,它们是可选的,原因是你的组件可能仅需要访问状态
但不需要分发任何 actions,反之亦然。
为了使用此方法,需要传入函数参数并在调用时传入组件。这种语法有些不寻常,如下所示:connect(mapStateToProps, mapDispatchToProps)(MyComponent)
注意: 如果要省略connect
方法中的某个参数,则应当用null
替换这个参数。
const addMessage = (message) => {
return {
type: 'ADD',
message: message
}
};
const mapStateToProps = (state) => {
return {
messages: state
}
};
const mapDispatchToProps = (dispatch) => {
return {
submitNewMessage: (message) => {
dispatch(addMessage(message));
}
}
};
class Presentational extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h3>This is a Presentational Component</h3>
}
};
const connect = ReactRedux.connect;
const ConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(Presentational);
React 和 Redux:将局部状态提取到 Redux 中
// Redux:
const ADD = 'ADD';
const addMessage = (message) => {
return {
type: ADD,
message: message
}
};
const messageReducer = (state = [], action) => {
switch (action.type) {
case ADD:
return [
...state,
action.message
];
default:
return state;
}
};
const store = Redux.createStore(messageReducer);
// React:
const Provider = ReactRedux.Provider;
const connect = ReactRedux.connect;
class Presentational extends React.Component {
constructor(props) {
super(props);
this.state = {
input: ''
}
this.handleChange = this.handleChange.bind(this);
this.submitMessage = this.submitMessage.bind(this);
}
handleChange(event) {
this.setState({
input: event.target.value
});
}
submitMessage() {
this.props.submitNewMessage(this.state.input);
this.setState({
input: ''
});
}
render() {
return (
<div>
<h2>Type in a new Message:</h2>
<input
value={this.state.input}
onChange={this.handleChange}/><br/>
<button onClick={this.submitMessage}>Submit</button>
<ul>
{this.props.messages.map( (message, idx) => {
return (
<li key={idx}>{message}</li>
)
})
}
</ul>
</div>
);
}
};
const mapStateToProps = (state) => {
return {messages: state}
};
const mapDispatchToProps = (dispatch) => {
return {
submitNewMessage: (message) => {
dispatch(addMessage(message))
}
}
};
const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);
class AppWrapper extends React.Component {
render() {
return (
<Provider store={store}>
<Container/>
</Provider>
);
}
};
React 和 Redux:从这里前进
写 React 和 Redux 的代码通常需要一些配置,可以通过别人配置好的创建 React App。
// 从'react'导入 React
import React from 'react';
// 从'react-dom'导入 ReactDOM
import ReactDOM from 'react-dom';
// 从'react-redux'导入{ Provider, connect }
import { Provider, connect } from 'react-redux';
// 从'redux'导入{ createStore, combineReducers, applyMiddleware }
import { createStore, combineReducers, applyMiddleware } from 'redux';
// 从'redux-thunk'导入 thunk
import thunk from 'redux-thunk';
// 从'./redux/reducers'导入 rootReducer
import rootReducer from './redux/reducers';
// 从'./components/App'导入 App
import App from './components/App';
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root')
);