How to Use React-Redux Basically
初步搞懂了 react-redux 的用法
前天周五看了半天 YouTube 视频,感觉终于搞懂了 react-redux 最简单的用法,也就是说,入门了、会用了。这让我非常有成就感,年纪大了,每学会一样新东西,都是一次青春的夺回。
共享状态
React 组件有个很重要的元素就是状态(state),状态决定 UI 的呈现结果。那么,怎样让组件 A 的状态影响组件 B 的状态呢,就需要一个全局状态,也就是状态需要被共享。Redux 的主要作用就是解决这个共享问题。
跟着大部分教程做,index.js
一般会被改成这样:
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
其中 store
就是一个存储共享状态的地方。组件如果要使用共享状态,就必须 connect
它:
export default connect()(YourComponent)
然后关键就是 connect()
里面的参数了,它决定了两件基本的事:
- 获取那些共享状态?
- 怎样改变共享状态?
Redux 三件套
Redux 比较麻烦的是,每个组件都需要三个文件去定义:
actionType
: 给每一个action.type
设定一个标识,用来比对。actions
: 定义方法名和对应的action.type
reducer
: 编写代码,设计每一个action
如何改变state
。
以 Login
为例:
Login/actionTypes.js
:
export const SIGN_IN = 'LOGIN/SIGN_IN';
export const SIGN_OUT = 'LOGIN/SIGN_OUT';
Login/actions.js
:
import { SIGN_IN, SIGN_OUT } from './actionTypes';
export const signIn = () => ({
type: SIGN_IN
});
export const signOut = () => ({
type: SIGN_OUT
});
Login/reducer.js
:
import { SIGN_IN, SIGN_OUT } from './actionTypes';
const initialState = {
isSignedIn: false
}
export default (state = initialState, action) => {
switch (action.type) {
case SIGN_IN: {
return {
isSignedIn: true
};
}
case SIGN_OUT: {
return {
isSignedIn: false
}
}
default: {
return state;
}
}
}
例子非常简单。signIn()
方法的 action.type
是 SIGN_IN
,这个 action
的作用就是把 isSignedIn
这个状态的值变成 true
,而signOut
是相反作用。
将 reducer 加入 store
Redux 组件的 reducer
做好后,必须添加到 store 里,才能被其他 react 组件用到。
各种教程都会用 combineReducers
来组合各种 reducer
:
const appReducer = combineReducers({
login: LoginReducer
});
现在,当 store
被创建好后,login.isSignedIn
就是个全局共享的 state
了。
connect
前面做的工作,都是为了 connect()
做准备。
假设有个控制登录和登出的菜单组件,名字叫 LoginMenuComponent
。组件有两个按钮,按 Sign In
登录,显示 Logged in
,按 Sign Out
登出,显示 Unauthenticated
。
为了 connect
,定义了两种关键方法 mapStateToProps
和 mapDispatchToProps
。
代码如下:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { signIn, signOut } from '../redux/Login/actions';
class LoginMenuComponent extends Component {
render = () => {
const { isSignedIn } = this.props;
return (
<button onClick={this.props.onSignIn}>Sign In</button>
<button onClick={this.props.onSignOut}>Sign Out</button>
{isSigned ? <p>Logged in.</p> : <p>Unauthenticated.</p>}
)
}
const mapStateToProps = state => ({
isSignedIn: state.login.isSignedIn
});
const mapDispatchToProps = (dispatch) => ({
onSignIn: () => {
dispatch(signIn());
},
onSignOut: () => {
dispatch(signOut());
}
});
}
其中,mapStateToProps
决定了组件的 props 用到哪个共享状态——login.isSignedIn
,而 mapDispatchToProps
决定了会用到哪些方法去改变这个共享状态,其中定义了onSignIn
和 onSignOut
两个方法,你在组件里可以通过 this.props.onSignIn()
和 this.props.onSignOut()
去执行它。
简单而言,这两个方法搞定了共享状态的”读“和”写“,基本上,就完事了,最后连接一下:
export default connect(mapStateToProps, mapDispatchToProps)(LoginMenuComponent);
一切就都 OK 了。如果有另一个组件通过它的 mapStateToProps
也读到了 login.isSignedIn
,那么这个状态就被这两个组件共享了,这样就可以做很多事了。