React 实践项目 (二)

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!

React 实践项目 (一)
本次实践代码

部署好的网址

上回说到用React写了一个带Header的首页,我们这次实践就使用Redux进行状态管理

Rudex

应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。
惟一改变 state 的办法是触发 action,一个描述发生什么的对象。
为了描述 action 如何改变 state 树,你需要编写 reducers。

我们接下来开始开始进行登陆与注册的状态管理

首先在 src 目录下创建 redux 文件夹,目录如下

digag
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   └── favicon.ico
│   └── index.html
│   └── manifest.json
└── src
    └── components
        └── Index
            └── Header.js
            └── LoginDialog.js
            └── RegisterDialog.js
    └── containers
        └── App
            └── App.js
            └── App.css
    └── redux
        └── action
            └── users.js
        └── reducer
            └── auth.js
            └── users.js
        └── sagas
            └── api.js
            └── sagas.js
            └── selectors.js.js
            └── users.js
        └── store
            └── store.js
    └── App.test.js
    └── index.css
    └── index.js
    └── logo.svg
    └── registerServiceWorker.js

代码可从此获取

记得在 package.json 中更新依赖

接下来我会开始解释关键代码

  • action
    action/users.js
/*
 * action 类型
 */
export const REGISTER_USER = ‘REGISTER_USER‘;
// 省略其他action 类型

/*
 * action 创建函数
 */
export const registerAction = (newUser) => {
  return{
    type:REGISTER_USER,
    data: newUser,
  }
};
// 省略其他 action 创建函数
  • reducer
    reducer/users.js
//Immutable Data 就是一旦创建,就不能再被更改的数据。
//对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
import Immutable from ‘immutable‘;
//从 action 导入需要的 action 类型
import {REGISTER_USER, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE} from ‘../action/users‘;

// 初始化状态
const initialState = Immutable.fromJS({
  newUser: null,
  error: null,
  saveSuccess: false,
});

//  reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
export const users = (state = initialState, action = {}) => {
  switch (action.type) { // 判断 action 类型
    case REGISTER_USER:
      return state.merge({   // 更新状态
        ‘newUser‘: action.data,
        ‘saveSuccess‘: false,
        ‘error‘: null,
      });
    case REGISTER_USER_SUCCESS:
      return state.set(‘saveSuccess‘, action.data);
    case REGISTER_USER_FAILURE:
      return state.set(‘error‘, action.data);
    default:
      return state
  }
};
  • store
    store/store.js
import {createStore, combineReducers, applyMiddleware } from ‘redux‘;
import createSagaMiddleware from ‘redux-saga‘
import * as reducer from ‘../reducer/users‘;

import rootSaga from ‘../sagas/sagas‘;

const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  combineReducers(reducer),
  applyMiddleware(sagaMiddleware)
);

sagaMiddleware.run(rootSaga);

export default store;

然后在入口文件使用 store

src/index.js

import {Provider} from ‘react-redux‘;
import store from ‘./redux/store/store‘;
// 省略其他

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>, document.getElementById(‘root‘)
);

在 App.js 中获取 action 和 状态

import {registerAction, loginAction} from ‘../../redux/action/users‘;
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
 //省略其他

class App extends Component {

  render(){
    return(
      <div className="App">
        //省略
      </div>
    )
  }

}

export default connect(
  (state) => {
// 获取状态   state.users  是指 reducer/users.js 文件中导出的 users
// 可以 `console.log(state);` 查看状态树
  return { users: state.users }
},
  (dispatch) => {
  return {
// 创建action
    registerActions: bindActionCreators(registerAction, dispatch),
    loginActions: bindActionCreators(loginAction, dispatch),
  }
})(App);
// 在App 组件的props里就有 this.props.users  this.props.registerActions this.props.loginActions 了
// 需要注意的是这里this.props.users是Immutable 对象,取值需要用this.props.users.get(‘newUser‘)
// 也可在 reducer 里改用 js 普通对象

装饰器版本:
需要在Babel中开启装饰器
装饰器插件babel-plugin-transform-decorators-legacy

@connect(
  (state) => {
    console.log(state);
    return ({
      users: state.users,
    });
  },
  {registerActions: registerAction, loginActions: loginAction}
)

最后把 registerActions 传给RegisterDialog子组件,

src/components/Index/RegisterDialog.js

// 省略其他代码
 handleSubmit = (e) => {
    e.preventDefault();
    // 验证表单数据
    this.refs.user.validate((valid) => {
      if (valid) {
        // this.state.user 为表单收集的 用户注册数据
        this.props.registerActions(this.state.user);
        this.setState({loading: true});
      }
    });
  };

流程是:

  • 调用 action
    this.props.registerActions(this.state.user);
    返回action 为
{
    type:REGISTER_USER,
    data: this.state.user,
}
  • reducer 根据action类型更新状态
switch (action.type) {
    case REGISTER_USER:
      return state.merge({
        ‘newUser‘: action.data,
        ‘saveSuccess‘: false,
        ‘error‘: null,
      });
//省略其他代码

这时我们的store里的状态 newUser就被更新为 注册弹窗里收集的数据
到这里都还是同步的action,而注册是一个异步的操作。
下篇文章会介绍如何使用 redux-saga 进行异步操作。
redux-saga 已经在使用了,有兴趣的可以自行查看代码理解。

记得点star:)
项目代码地址:https://github.com/DigAg/digag-pc-react
vue2版项目代码地址:https://github.com/DigAg/digag-pc-vue2
相应后端项目代码地址:https://github.com/DigAg/digag-server

时间: 2024-08-07 23:10:37

React 实践项目 (二)的相关文章

React 实践项目 (三)

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作 React 实践项目 (一)React 实践项目 (二)React 实践项目 (三) - 首先我们来看看登陆的 Reducer export const auth = (state = initialState, actio

React 实践项目 (四)

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 上回说到使用Redux-saga 管理 Redux 应用异步操作,应用还是只有一个首页.现在开始构建一个新的投稿页面并使用 React-Router 进行路由管理. React 实践项目 (一)React 实践项目 (二)React 实践项目 (三)React 实践项目 (四) - 首先我们来构建投稿页面 创建 src/co

React 实践项目 (五)

React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一)React 实践项目 (二)React 实践项目 (三)React 实践项目 (四)React 实践项目 (五) 这次我们把应用部署到服务器上. 项目到现在麻雀虽小五脏俱全,为了提高我们写代码的积极性,自然是选择部署到服务器上在小伙伴面前秀一波了.部署 React 应用也是非常方便简单的. 打包应

Springboot + mybatis + React+redux+React-router+antd+Typescript(二): React+Typescrip项目的搭建

前言: 后台搭建完以后开始搭建前端,使用create-react-app搭建项目非常方便. 前端主要是如何向后台请求数据,以及如何使用redux管理state,路由的配置. 前端github地址: https://github.com/www2388258980/rty-web 后台github地址: https://github.com/www2388258980/rty-service 项目访问地址:          http://106.13.61.216:5000/          

【腾讯Bugly干货分享】React Native项目实战总结

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 "8小时内拼工作,8小时外拼成长"这是大家共同的理想.除了每天忙于工作外,我们都希望能更多地区吸收领域内的新知识与新技能,从而走向人生巅峰. Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员都是经过审核的移动开发工程师.每周都会举行嘉宾分享,话题讨论等活动. 上一期我们邀请了腾讯SNG工程师&qu

微软云计算介绍与实践(实践之二十)

接上面章节,有同学说为什么要搞这么一些东西,刚好我给大家贴一张图,看一下微软私有云解决方案中这几大组件相互关系,看完后大家也就明白我今天为什么还在做各种环境搭建,配置准备工作了. 一.配置System Center 2012虚拟机管理器集成包 上一章节,小张同学可以使用已有的的集成包,但他需要配置一下它们,让其和服务器正确连接.在接下来的步骤中,小张同学是要配置的是他刚刚注册和部署的四个集成包.关于使用集成包的先决条件.可以参考如下TechNet网页:http://technet.microso

android 实践项目 总结 (修改)

Android开发项目:百度地图的调用 在一个不熟悉的环境中,获得自己的位置,选择合适的就餐地点,住宿和公交路线成为一项难题.本次的实践项目就是为了解决上述难题的,通过调用百度地图的接口实现定位.查询公交路线.寻找合适的餐饮及住宿等功能,满足人们出行功能. 一 需求分析 1.1 客户需求 一个项目的开发,首先要了解客户的需求,否则这个项目没有任何开发的价值.在社会快速发展的今天,人员流通较快,选择合适的交通线路.餐馆及住宿成为一项难题,因此根据客户的需求,进行开发合适的项目来满足客户的需求. 1

Android实践项目汇报

Android实践项目:推箱子 推箱子是一款来自日本的古老游戏,其设计目的是训练人的逻辑思维能力.游戏场景一般是设定在空间狭小的仓库中,要求把箱子摆放到指定位置.这就要求玩家巧妙的运用有限的空间和通道,合理的安排箱子的位置和移动次序才可能完成任务. 随着计算机游戏的发展,很多编程爱好者基于该游戏的思想开发了出各种版本.各种类型的推箱子.这其中也包括很多手机版本的实现,伴随着手机与计算机的普及,很快推箱子游戏便进入了千家万户. 一.需求分析: 2.1 功能需求 在游戏开发之前,首先需要对游戏所应该

DDD实践切入点(二)

承前:大型系统的支撑,应用系统开发思想的变迁,DDD实践切入点(一) 从大比例结构入手已经开始了系统的建设,大家都知道需求是会不断变化不断深入的,刚开始自然是模糊的大比例结构对将要进行的系统有一个初步的认识,在不断细化的过程中明确需求.前一篇中粗略的对主要的问题进行了描述,可以看出主要有两个部分,申请单管理和审批流转,两者都与申请单关联,但关注点不同,申请单管理的重点是对申请单本身信息的维护,而审批流转中主要是以申请单的部分信息为依据进行流转的决策,所以两者申请单的模型有些许不同. 领域模型不统