教程:让我们构建一个由 Redux 驱动的 React 应用
在这篇文章,我们将深入探讨 Redux 并了解为什么用它构建一个 React 应用时是很有价值的。我也将带您构建您的第一个 Redux 应用,包括如何使用 Stormpath React SDK 作为 身份认证。之后您可以把这些知识应用到您现有的 React 应用中! 什么是 Redux?Redux 是一个帮您在应用中管理 state 的库。它的设计源自 Flux,但是避开了 Flux 编写应用的复杂性。如果您已经编写了一个 Flux 应用,您会很快发现使用 Redux 需要手动编写之前所有的样板。此外与 Flux 不同的是,您有一个单一的 state 容器。这是一个很大的优势,因为它会使 state 共享和代码重用让您构建应用轻松很多。 Storesstore 仅是一个 state 容器。这是存储 state 并在哪里 actions 被调度及处理的地方。当您开始构建一个 Redux 应用,您要思考如何在应用中存储模块和 state。这很重要因为 Redux 建议只有一个 store,并且由于 state 共享这是之前想到的一个不错的想法。 ActionsActions 是表示如何周转我们 state 状态的对象。您可以把 actions 视为 state 树的 API。为了说明,一个添加新用户的 action 可以是: { type: 'ADD_USER',data: { name: 'Foo',email: 'foo@bar.com',password: 'Foobar123_' } } 为了让操作变得更清晰和更容易复用,通常使用一个建造者模式来创建 action 对象。例如在上述情况,您可以为这个对象创建一个函数如 ReducersActions 很酷,但它们对自身并没有太大的意义。这就是 reducers 的由来。Reducers 在 store 中通过分发处理 action 来减少这些 actions 对 state 的改变。如果我们在 store 分发一个 action 如 构建 Redux 应用现在您了解了基础知识,让我们继续设计和构建第一个由 Redux 驱动的应用。 为了让操作变的简单,我们构建一个 to-do 应用。这样我们就可以玩转大部分 Redux 中最重要的概念而不是过于关注于应用自身。 如果我们想到一个 to-do 应用,我们将会需要一些基本的事项。首先一个 to-do 通常由一个列表组成。另外,这个列表包含我们可以更改的待办事项。 从一个 state 角度来看,我们这个应用的模型类似这样: { todo: { items: [ { message: "Finish Redux blog post...",completed: false } ] } } 添加 Actions添加待办事项到 state ?首先,我们希望添加新的待办事项到其中。让我们创建一个 action : function addTodo(message) { return { type: 'ADD_TODO',message: message,completed: false }; } 注意这里的 一旦我们增加了新的待办事项,我们肯定希望能够将其标记为已完成,我们也希望能够将其删除,甚至可以清除所有待办事项。 因此让我们也为这些操作添加 actions : function completeTodo(index) { return { type: 'COMPLETE_TODO',index: index }; } function deleteTodo(index) { return { type: 'DELETE_TODO',index: index }; } function clearTodo() { return { type: 'CLEAR_TODO' }; } 现在我们已经有了 actions,让我们继续构建 store。如果您还记的刚刚说的,store 是 Redux 应用的核心,关联所有的 state,调度 actions 和 reducers 处理。 import { createStore } from 'redux'; var defaultState = { todo: { items: [] } }; function todoApp(state,action) { } var store = redux.createStore(todoApp,defaultState); 添加 Reducers现在当我们有一些 actions 和 store,让我们创建第一个 reducer。如果您还记的刚刚说的,reducer 只是一个处理器您可以用它来处理 actions 和改变 state。 因此我们开始处理 function todoApp(state,action) { switch (action.type) { case 'ADD_TODO': return Object.assign({},state,{ items: items.concat([{ message: action.message,completed: false }]) }); default: return state; } } 注意当我们说一个 reducer “改变” state 时,如果一个 state 需要改变,实际它所做的是创建一个 state 副本并作出改变。如果没有变化,那么返回相同的 state。但在任何情况下您都不应该直接改变 state 因为这样意味着改变 state history 。 现在当我们有了第一个 action 处理器,让我们为它们增加其余的支持: function todoApp(state,{ todo: { items: items.concat([{ message: action.message,completed: false }]) } }); case 'COMPLETE_TODO': var items = [].concat(state.todo.items); items[action.index].completed = true; return Object.assign({},{ todo: { items: items } }); case 'DELETE_TODO': var items = [].concat(state.todo.items); items.splice(action.index,1); return Object.assign({},{ todo: { items: items } }); case 'CLEAR_TODO': return Object.assign({},{ todo: { items: [] } }); default: return state; } } 把它们结合到一个 React 界面现在我们已经有了业务逻辑,让我们写一些 UI 代码。由于大部分是常见的 React 知识并且非常类似 Flux 构建的应用,就不再深入讲解。 import React from 'react'; import ReactDOM from 'react-dom'; import { createStore } from 'redux'; var defaultState = { todo: { items: [] } }; // 添加我们在前面步骤中创建的 actions ... function todoApp(state,action) { // 添加我们在前面步骤中的 reducer 逻辑... } var store = redux.createStore(todoApp,defaultState); class AddTodoForm extends React.Component { state = { message: '' }; onFormSubmit(e) { e.preventDefault(); store.dispatch(addTodo(this.state.message)); this.setState({ message: '' }); } onMessageChanged(e) { var message = e.value.trim(); this.setState({ message: message }); } render() { return ( <form onSubmit={this.onFormSubmit.bind(this)}> <input type="text" placeholder="Todo..." onChange={this.onMessageChanged.bind(this)} value={this.state.message} /> <button type="submit" value="Add" /> </form> ); } } class TodoItem extends React.Component { onDeleteClick() { store.dispatch(deleteTodo(this.props.index)); } onCompletedClick() { store.dispatch(completeTodo(this.props.index)); } render() { return ( <li> <a href="#" onClick={this.onDeleteClick.bind(this)}>[x]</a> <a href="#" onClick={this.onCompletedClick.bind(this)}>{this.props.message}</a> </li> ); } } class TodoList extends React.Component { state = { items: [] }; componentWillMount() { store.subscribe(() => { var state = store.state(); this.setState({ items: state.todo.items }); }); } render() { var items = []; this.state.items.forEach((item,index) => { items.push(<TodoItem index={index} message={item.message} completed={item.completed} />); }); return ( <ol>{ items }</ol> ); } } ReactDOM.render( <div> <h1>Todo</h1> <AddTodoForm /><hr /> <TodoList /> </div>,document.getElementById('app') ); 正如您所看到的,构建 Redux 应用 UI 部分并不难。唯一的区别就是您用 Redux 支持 Stormpath React SDK因为有相当多需要增加 Redux 支持 Stormpath React SDK 需求,我们说干就干。如果您希望为 Redux 配置这个 SDK,简单的配置这个 Stormpath React SDK function myApp(state,action) { return state; } ReactStormpath.init({ dispatcher: { type: 'redux',store: createStore(myApp) } }); 一旦完成这些您可以拦截并处理一切 Stormpath React SDK 的 actions 调度。例如,您希望用用户数据来丰富 state,然后简单处理这个 function myApp(state,action) { switch (action.type) { case 'USER_SET': return Object.assign({},{ user: action.data }); default: return state; } } 结束语正如您在这篇文章所看到的,构建一个由 Redux 驱动的应用是非常容易和简单的。这很像构建一个 Flux,只是是概念略有不同并有较少的样板代码编写。 希望您喜欢这个教程,能够在将来利用它。 如果遇到任何无法运行或者问题,不妨看下 参考应用。 延伸阅读想了解更多关于 React 应用增加身份认证的内容?看看这些教程:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- applicationContext.xml中<context:annotation-c
- iOS图片自适应屏幕 截取
- WPF整理-为User Control添加依赖属性
- API(全局配置,全局API)
- flex air mx:HTML target=_blank 无效解决办法!
- oracle中transaction是不是只有commit之后才能完
- QT14 how to save data in sqlite database with
- 如何在unmarshal期间使用JAXB XmlAdapter处理XML
- tiny210(s5pv210)移植u-boot(基于 2014.4 版本)—
- cocos2dx自学之 动作特效与场景切换特效