[AngularJS] Write a simple Redux store in AngularJS app
The first things we need to do is create a reducer:
/** * CONSTANT * @type {string} */ export const GET_CATEGORIES = "GET_CATEGORIES"; /** * INIT VALUE */ export const initialCategories = [ {id: 0, name: 'Development'}, {id: 1, name: 'Design'}, {id: 2, name: 'Exercise'}, {id: 3, name: 'Humor'} ]; /** * REDUCERS * @type {string} */ export const categories = (state = initialCategories, {type, payload}) => { switch(type) { case GET_CATEGORIES: return payload || state; default: return state; } };
It has some default initialize data. What it does is just simply return the state.
Then let's create a gloable store for the app, which has two methods, getState, dispatch. Two props: reducer, state.
class Store { constructor(reducer, initialState) { this.reducer = reducer; this.state= initialState; } getState() { return this.state } dispatch() { this.state = this.reducer(this.state, action); } }
Once we got that, we are going to init our store:
import {categories, initialCategories} from './components/categories/category.state'; import Store from './app.store'; const store = new Store(categories, initialCategories);
We passed in categoreis reudcer and the initialCategories state.
To make it available to Angular APP. we need to make it injectable:
let appModule = angular.module('app', [ CommonModule.name, ComponentsModule.name ]) .value('store', store)
Then we can use it in our app:
class CategoriesController { constructor(store) { 'ngInject'; angular.extend(this, { store }); } $onInit() { this.store.dispatch({type: GET_CATEGORIES}); this.categories = this.store.getState(); } }
Now we are going to simply the code a little bit, we going to make a subscribe method so that we don't need to call getState() method everytime after we dispatch an action.
You can think that the subscribe method is a just callback function which each time we dispatch an action, it will be called. And inside the callback function, we will call this.store.getState() to get the value.
class Store { constructor(reducer, initialState) { this.reducer = reducer; this.state = initialState; this.listeners = []; } getState() { return this.state; } dispatch(action) { this.state = this.reducer(this.state, action); this.listeners.forEach((l) => l()); } subscribe(listener) { this.listeners = [ ...this.listeners, listener ]; // return an unsubscribe function return () => { this.listeners = this.listeners.filter(l => l !== listener); } } } export default Store;
class CategoriesController { constructor($timeout, store) { 'ngInject'; angular.extend(this, { $timeout, store }); } $onInit() { this.unsubscribe = this.store.subscribe(() => { this.categories = this.store.getState(); }); this.store.dispatch({type: GET_CATEGORIES}); } }
Currently inside the dispatch() metod, we pass in an object with type and payload. It would be better if we can manage those action in a single place. There is where Action creator comes in to play.
/** * ACTIONS CREATOR */ export const CategoriesActions = () => { const getCategoreis = (categories) => { return {type: GET_CATEGORIES, payload: categories} }; const getCurrentCategory = (currentCategory) => { return {type: GET_CURRENT_CATEGORY, payload: currentCategory} }; return { getCategoreis, getCurrentCategory }; };
To make it avaiable to Angular App, we can create a factory for this:
let appModule = angular.module('app', [ CommonModule.name, ComponentsModule.name ]) .value('store', store) .factory('CategoriesActions', CategoriesActions) .component('app', AppComponent)
Then we can use it inside the controller:
constructor($timeout, store, CategoriesActions) { 'ngInject'; angular.extend(this, { $timeout, store, CategoriesActions }); }
$onInit() { this.unsubscribe = this.store.subscribe(() => { this.categories = this.store.getState(); }); this.store.dispatch(this.CategoriesActions.getCategoreis()); }
onCategorySelected(currentCategory) { this.currentCategory = category(this.currentCategory, this.CategoriesActions.getCurrentCategory(currentCategory)); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2015-11-09 [Falcor] Indroduce to Model
2015-11-09 [Farcol] Introduce
2015-11-09 [Angualr 2] Watch for changes
2015-11-09 [Angular 2] Custom Validtors
2015-11-09 [Angular 2] The form export from NgFormControl
2014-11-09 [Angular-Scaled Web] 6. Navigating between states with ui-router
2014-11-09 [Angular-Scaled web] 5. ui-router $stateParams for sharing information