React 实践项目 (二)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!
上回说到用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
React 实践项目 (二)的更多相关文章
- React 实践项目 (三)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 上回说到使用Redux进行 ...
- React 实践项目 (五)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一 ...
- React 实践项目 (一)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 项目代码地址:https: ...
- python实践项目二:列表转字符串
将列表各元素转换为字符串并以规定形式返回. 假定有下面这样的列表:spam = ['apples', 'bananas', 'tofu', 'cats'],将其转换成字符串:'apples, bana ...
- Immutable.js 以及在 react+redux 项目中的实践
来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...
- 20155320 2016-2017-2《Java程序设计》第十二周课堂实践项目
20155320 2016-2017-2<Java程序设计>第十二周课堂实践项目 1.修改教材P98 Score2.java, 让执行结果数组填充是自己的学号: 2.在IDEA中以TDD的 ...
- 在React旧项目中安装并使用TypeScript的实践
前言 本篇文章默认您大概了解什么是TypeScript,主要讲解如何在React旧项目中安装并使用TypeScript. 写这个的目的主要是网上关于TypeScript这块的讲解虽然很多,但都是一些语 ...
- 技术实践丨React Native 项目 Web 端同构
摘要:尽管 React Native 已经进入开源的第 6 个年头,距离发布 1.0 版本依旧是遥遥无期."Learn once, write anywhere",完全不影响 Re ...
- 【腾讯Bugly干货分享】React Native项目实战总结
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...
随机推荐
- OpenCV探索之路(十三):详解掩膜mask
在OpenCV中我们经常会遇到一个名字:Mask(掩膜).很多函数都使用到它,那么这个Mask到底什么呢? 一开始我接触到Mask这个东西时,我还真是一头雾水啊,也对无法理解Mask到底有什么用.经过 ...
- 5.Java 加解密技术系列之 DES
Java 加解密技术系列之 DES 序 背景 概念 基本原理 主要流程 分组模式 代码实现 结束语 序 前 几篇文章讲的都是单向加密算法,其中涉及到了 BASE64.MD5.SHA.HMAC 等几个比 ...
- 开涛spring3(7.4) - 对JDBC的支持 之 7.4 Spring提供的其它帮助
7.4 Spring提供的其它帮助 7.4.1 SimpleJdbc方式 Spring JDBC抽象框架提供SimpleJdbcInsert和SimpleJdbcCall类,这两个类通过利用JDB ...
- LiteIDE灰调配色方案
说明 本文写于2017-04-03,使用LiteIDE X31(基于Qt 4.8.5),操作系统为Windows. 使用 LiteIDE下载后解压即可使用.配色方案的所有配置文件都位于liteide/ ...
- 深度解析PHP数组函数array_chunk
array_chunk是PHP中的一个数组分割函数,是将一个数组分割为多个数组块 我们可以把它理解卖豆腐的商人把一整块大豆腐切割为一个一个的小块来进行售卖 这个函数需要三个参数: 被切割的数组(必需) ...
- Mac苹果系统 多系统启动:The rEFInd Boot Manager
苹果系统 多系统启动 下载安装REFIT: 首先安装一下:REFIT, 在这个页面下载: http://refit.sourceforge.net/#download 选择mac disk image ...
- Qt之添加图标
导读: 在使用Qt Creator编写完应用程序后,设置release版的应用程序图标着实困扰了不少的人.一个漂亮的图标是一个软件的脸,没有一个漂亮的图标,那么这个程序是不完整的.那么我们来看看如何设 ...
- JVM-2.Class文件结构
1.Class文件 (1)无关性:除了平台无关性,JVM还支持语言无关性:目前Clojure.Groovy.JRuby.Jyphon.Scala等语言可以在JVM上运行.实现语言无关性的原理仍然是字节 ...
- Vivado2015.4使用教程(一个完成工程的建立)
双击桌面的vivado图标,(可能有点慢) 弹出主菜单界面,点击create new project 这是介绍界面,next~ 添加好工程名,和工程位置,next~ 选择rtl Project,nex ...
- Windows系统如何使用sqlmap
使用方法:需要安装python,不能安装最新版本的python3.2.2只能安装2.6-3.0这些版本,包括2.6,3.0 这里,我提供一个Python的安装包.点击这里下载→ Python2.7 然 ...