分享一个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,而注册是一个异步的操作。
以上是分享一个React的实践项目的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

费马大定理,即将被AI攻克?而且整件事最意味深长的地方在于,AI即将解决的费马大定理,正是为了证明AI无用。曾经,数学属于纯粹的人类智力王国;如今,这片疆土正被先进的算法所破译,所践踏。图片费马大定理,是一个「臭名昭著」的谜题,在几个世纪以来,一直困扰着数学家们。它在1993年被证明,而现在,数学家们有一个伟大计划:用计算机把证明过程重现。他们希望在这个版本的证明中,如果有任何逻辑上的错误,都可由计算机检查出来。项目地址:https://github.com/riccardobrasca/flt

标题:深入了解PyCharm:删除项目的高效方式近年来,Python作为一种强大而灵活的编程语言,受到越来越多开发者的青睐。在Python项目的开发中,选择一个高效的集成开发环境至关重要。PyCharm作为一款功能强大的集成开发环境,为Python开发者提供了诸多便利的功能和工具,其中包括快速、高效地删除项目目录。下面将着重介绍如何使用PyCharm中的删除

PyCharm是一款功能强大的Python集成开发环境,提供了丰富的开发工具和环境配置,让开发者能够更高效地编写和调试代码。在使用PyCharm进行Python项目开发的过程中,有时候我们需要将项目打包成可执行的EXE文件,以便在没有安装Python环境的计算机上运行。本文将介绍如何使用PyCharm将项目转换为可执行的EXE文件,同时给出具体的代码示例。首

作为一款电子邮件管理器应用程序,MicrosoftOutlook允许我们安排活动和约会。它通过提供在Outlook应用程序中创建、管理和跟踪这些活动(也称为事件)的工具,使我们能够保持有序。然而,有时会将不需要的事件添加到Outlook中的日历中,这会给用户造成混乱,并向日历发送垃圾邮件。在本文中,我们将探讨可帮助我们防止Outlook自动将事件添加到我的日历中的各种方案和步骤。Outlook活动-简要概述Outlook事件具有多种用途,并具有许多有用的功能,具体如下:日历集成:在Outlook

织梦CMS站群实践分享近年来,随着互联网的快速发展,网站建设变得越来越重要。在建设多个网站时,站群技术成为了一个非常有效的方法。而在众多网站建设工具中,织梦CMS凭借其灵活性和易用性成为了不少站群爱好者的首选。本文将分享一些关于织梦CMS站群的实践经验,以及一些具体的代码示例,希望能为正在探索站群技术的读者提供一些帮助。1.什么是织梦CMS站群?织梦CMS

Struts框架的原理解析与实践探索Struts框架作为JavaWeb开发中常用的MVC框架,具有良好的设计模式和可扩展性,广泛应用于企业级应用程序开发中。本文将对Struts框架的原理进行解析,并结合实际代码示例进行探索,帮助读者更好地理解和应用该框架。一、Struts框架的原理解析1.MVC架构Struts框架基于MVC(Model-View-Con

Java框架与React框架的整合:步骤:设置后端Java框架。创建项目结构。配置构建工具。创建React应用。编写RESTAPI端点。配置通信机制。实战案例(SpringBoot+React):Java代码:定义RESTfulAPI控制器。React代码:获取并显示API返回的数据。

PHP编码实践:拒绝使用goto语句的替代方案近年来,随着编程语言的不断更新和迭代,程序员们开始更加注重编码规范和最佳实践。在PHP编程中,goto语句作为一种控制流语句存在已久,但在实际应用中往往会导致代码的可读性和可维护性下降。本文将分享一些替代方案,帮助开发人员拒绝使用goto语句,提高代码质量。一、为什么拒绝使用goto语句?首先,让我们来思考一下为
