在模板中,我们集成了 Redux 作为应用的状态管理,但这不是唯一的,你可以选择你熟悉的其他状态管理类的库。

使用

在模板中,我们提供了基础的 redux 示例,避免使用起来过于繁琐和要删除大量不必要的代码。模板中完成了从 注册 => 登录 => 获取用户信息 =》权限判断 =》 主页 的完整示例。下面以登录模块为例来了解我们是如何使用 redux 的。

分型结构

我们推荐按照功能模块来组织我们的 redux 代码,如下结构,而不是把所有的 action 或者 reducer 集中化管理,避免项目在发展过程中一个 actions 目录下面出现几十甚至是上百个 action 文件,修改或者是删除一个文件需要在不同的目录下查找。这是我们按照功能模块来组织的最简单的原因之一。

  1. .
  2. ├── UserLogin.jsx
  3. ├── actions.js
  4. ├── constants.js
  5. ├── index.js
  6. └── reducer.js

状态容器

Redux 可以方便的管理你的应用状态,提供可预测的状态管理,下面是模板中的一个完整示例:

Constants

  1. /*
  2. * LoginConstants
  3. *
  4. * Each action has a corresponding type, which the reducer knows and picks up on.
  5. * To avoid weird typos between the reducer and the actions, we save them as
  6. * constants here. We prefix them with 'yourproject/YourComponent' so we avoid
  7. * reducers accidentally picking up actions they shouldn't.
  8. *
  9. * Follow this format:
  10. * export const YOUR_ACTION_CONSTANT = 'yourproject/YourContainer/YOUR_ACTION_CONSTANT';
  11. */
  12. export const USER_LOGIN_REQUEST = 'PRO/USER_LOGIN_REQUEST';
  13. export const USER_LOGIN_FAILURE = 'PRO/USER_LOGIN_FAILURE';
  14. export const USER_LOGIN_SUCCESS = 'PRO/USER_LOGIN_SUCCESS';
  15. **Action Creators**
  16. /*
  17. * Login Actions
  18. */
  19. import {
  20. USER_LOGIN_REQUEST,
  21. USER_LOGIN_SUCCESS,
  22. USER_LOGIN_FAILURE,
  23. } from './constants';
  24. /**
  25. * Changes the input field of the form
  26. *
  27. * @param {name} name The new text of the input field
  28. *
  29. * @return {object} An action object with a type of CHANGE_USERNAME
  30. */
  31. const userLoginRequest = () => {
  32. return {
  33. type: USER_LOGIN_REQUEST,
  34. isLoading: true,
  35. };
  36. };
  37. const userLoginSuccess = (payload) => {
  38. return {
  39. type: USER_LOGIN_SUCCESS,
  40. payload,
  41. isLoading: false,
  42. };
  43. };
  44. const userLoginFailure = (payload) => {
  45. return {
  46. type: USER_LOGIN_FAILURE,
  47. payload,
  48. isLoading: false,
  49. };
  50. };
  51. export const userLogin = (params) => {
  52. return async (dispatch) => {
  53. dispatch(userLoginRequest());
  54. try {
  55. const response = await login(params);
  56. dispatch(userLoginSuccess(response.data));
  57. } catch (error) {
  58. dispatch(userLoginFailure(error));
  59. }
  60. };
  61. };

Reducer

  1. /*
  2. * LoginReducer
  3. *
  4. */
  5. import {
  6. USER_LOGIN_REQUEST,
  7. USER_LOGIN_SUCCESS,
  8. USER_LOGIN_FAILURE,
  9. } from './constants';
  10. // The initial state of the login
  11. const initialState = {};
  12. function loginReducer(state = initialState, action) {
  13. switch (action.type) {
  14. case USER_LOGIN_REQUEST:
  15. return Object.assign({}, state, {
  16. isLoading: action.isLoading,
  17. });
  18. case USER_LOGIN_SUCCESS:
  19. return Object.assign({}, state, {
  20. isLoading: action.isLoading,
  21. ...action.payload,
  22. });
  23. case USER_LOGIN_FAILURE:
  24. return Object.assign({}, state, {
  25. isLoading: action.isLoading,
  26. });
  27. default:
  28. return state;
  29. }
  30. }
  31. export default loginReducer;

Container

  1. class UserLogin extends Component {
  2. static displayName = 'UserLogin';
  3. static propTypes = {};
  4. static defaultProps = {};
  5. constructor(props) {
  6. super(props);
  7. this.state = {};
  8. }
  9. render() {
  10. return (
  11. ...
  12. );
  13. }
  14. }
  15. const mapDispatchToProps = {
  16. userLogin,
  17. };
  18. const mapStateToProps = (state) => {
  19. return { loginResult: state.login };
  20. };
  21. const withConnect = connect(
  22. mapStateToProps,
  23. mapDispatchToProps
  24. );
  25. const withReducer = injectReducer({ key: 'login', reducer });
  26. export default compose(
  27. withReducer,
  28. withConnect
  29. )(UserLogin);