راهنمای گام به گام برای مدیریت State با NgRx در Angular 16

کتابخانه NGRX یک کتابخانه محبوب برای مدیریت state ها در برنامه های Angular است. این کتابخانه کمک می کند تا وضعیت یک برنامه را به روشی قابل پیش بینی و مقیاس پذیر مدیریت کنید. در این راهنما، فرآیند پیاده سازی NGRX را با ساختن یک اپلیکیشن کوچک Todo به صورت گام به گام طی خواهیم کرد.در اینجا می توانید به کد کامل مراجعه کنید.مرحله 1: NGRX را نصب کنید.برای نصب NGRX، دستور زیر را در ترمینال خود اجرا کنید:npm install @ngrx/store @ngrx/effects --saveپکیج ngrx/store@ توابع اصلی مدیریت حالت را برای NGRX فراهم می کند. پکیجngrx/effectsراهی برای رسیدگی به اثرات جانبی در برنامه شما فراهم می کند.ساختار پوشه برنامه ما به این شکل خواهد بود.src/ | store/ | actions.ts | reducers.ts | selectors.ts | store.ts | todo.model.ts | main.ts | todo.component.ts | todo.component.htmlمرحله 2: مدل Todo را تعریف کنید.اولین قدم این است که مدل داده های خود را در store/todo.model.tsرا تعریف کنید.export interface Todo { id: number | string; description: string; completed: boolean; }در این مثال، interface Todo را با برخی ویژگی ها تعریف می کنیم.مرحله 3: Service و Actions را تعریف کنید.سرویس ما شامل سرویس api todo با تابعgetAllخواهد بود. این به عنوان یک سرویس ، جواب بکند را شبیه سازی میکند . ما از Observable استفاده خواهیم کرد و از تأخیر یا delay برای نمایش لودر استفاده خواهیم کرد.سرویس todo را در store/service.tsتعریف کنید.@Injectable() export class ToDoService { // fake backend getAll(): Observable<Todo[]> { return of( [{ id: 1, description: 'description 1', completed: false }, { id: 2, description: 'description 2', completed: false }] ).pipe(delay(2000)) } }اکشن ها پیام‌هایی هستند که تغییر حالت در برنامه شما را توصیف می‌کنند. آنها اشیاء جاوا اسکریپت هستند که دارای یک ویژگی نوع (type) و یک payload اختیاری هستند. action ها را در store/actions.tsتعریف کنید.export const loadTodos = createAction('[Todo] Load Todos'); export const loadTodosSuccess = createAction('[Todo] Load Todos Success', props<{ todos: Todo[] }>()); export const loadTodosFailure = createAction('[Todo] Load Todos Failure', props<{ error: string }>()); export const addTodo = createAction('[Todo] Add Todo', props<{ todo: Todo }>()); export const updateTodo = createAction('[Todo] Update Todo', props<{ todo: Todo }>()); export const deleteTodo = createAction('[Todo] Delete Todo', props<{ id: string }>());در این مثال چندین اکشن برای مدیریت حالتTodoتعریف می کنیم. اکشن loadTodosبرای بارگیری لیست کارهای انجام شده از سرور استفاده می شود. اکشنloadTodosSuccessزمانی که کارها با موفقیت بارگیری شوند، ارسال می شود .اکشن loadTodosFailureزمانی که در بارگیری کارها خطایی وجود داشته باشد، ارسال می شود . از اکشن های addTodo, updateTodoو deleteTodoبه ترتیب برای به روز رسانی ، افزودن و حذف todoها استفاده می شود.مرحله 4: Reducer ها را تعریف کنید.کاهنده ها یا reducerها توابعی هستند که حالت فعلی و یک اکشن را می گیرند و حالت جدیدی را برمی گردانند. آنها مسئول رسیدگی به تغییرات حالت در برنامه شما هستند. آن ها را درstore/reducers.tsتعریف کنید.export interface TodoState { todos: Todo[]; loading: boolean; error: string; } export const initialState: TodoState = { todos: [], loading: false, error: '' }; export const todoReducer = createReducer( initialState, on(TodoActions.loadTodos, state => ({ ...state, loading: true })), on(TodoActions.loadTodosSuccess, (state, { todos }) =>({ ...state, todos, loading: false })), on(TodoActions.loadTodosFailure, (state, { error }) => ({ ...state, error, loading: false })), on(TodoActions.addTodo, (state, { todo }) => ({ ...state, todos: [...state.todos, todo] })), on(TodoActions.updateTodo, (state, { todo }) => ({ ...state, todos: state.todos.map(t => t.id === todo.id ? todo : t) })), on(TodoActions.deleteTodo, (state, { id }) => ({ ...state, todos: state.todos.filter(t => t.id !== id) })), );در این مثال یک reducer برای مدیریت حالتTodoتعریف می کنیم. تابع initialState،todoReducerو مجموعه ای از توابع reducerها را می گیرد که با استفاده از تابعonاز @ngrx/storeتعریف شده اند. هر تابع reducer یک عمل خاص را انجام می دهد و یک حالت جدید را برمی گرداند.مرحله 5: Effect ها را تعریف کنید.افکت‌ها سرویس‌هایی هستند که به اکشن ها گوش می‌دهند و اثرات جانبی مانند درخواست‌های HTTP یا تعامل با APIهای مرورگر را انجام می‌دهند.@Injectable() export class TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ofType(TodoActions.loadTodos), mergeMap(() => this.todoService.getAll().pipe( map((todos) => TodoActions.loadTodosSuccess({ todos })), catchError((error) => of(TodoActions.loadTodosFailure({ error: error.message })) ) ) ) ) ); constructor(private actions$: Actions, private todoService: ToDoService) {} }در این مثال، یک افکت برای مدیریت اکشنloadTodosتعریف می کنیم. افکت loadTodos$به اکشنloadTodosبا استفاده از عملگرofTypeازngrx/effects@ گوش می دهد . هنگامی که اکشن ارسال می شود، افکت متدgetAllرا از TodoServiceفراخوانی می کند و بسته به نتیجه اکشنloadTodosSuccessیا loadTodosFailureرا ارسال می کند.مرحله 6: تعریف interface برای Storeاینترفیس در فایلstore/store.ts تعریف خواهد شد .export interface AppState { todo: TodoState } export interface AppStore { todo: ActionReducer<TodoState, Action>; } export const appStore: AppStore = { todo: todoReducer } export const appEffects = [TodoEffects];اینترفیسAppStateتمام ویژگی های feature برنامه را تعریف می کند. در اینجا ما یک feature واحد داریم بنامtodo که از نوعTodoState است . ما می توانیم چندین feature در برنامه خود مانند این داشته باشیم.اینترفیسAppStoreتمام انواع reducer های مورد استفاده در برنامه ما را تعریف می کند. در این مورد، ما یک reducer برای todo داریم، بنابراین ما todoReducerرا به ویژگیtodoنسبت میدهیم. appStoreبرای پیکربندی ماژول store ما استفاده خواهد شد.اینappEffectsآرایه ای از کلاس های افکت های تعریف شده را خواهد داشت. این برای ثبت effectها در برنامه استفاده می شود.مرحله 7: Store and Effects را در کامپوننت standalone اصلی ثبت کنید.برای استفاده از store NGRX در برنامه خود، باید آن را درStoreModuleدر AppModuleخود ثبت کنید . ما در اینجا از کامپوننت های مستقل استفاده خواهیم کرد.@Component({ selector: 'my-app', standalone: true, imports: [ CommonModule ], template: ``, }) export class App { } bootstrapApplication(App, { // register the store providers here providers: [ provideStore(appStore), provideEffects(appEffects), ToDoService ] });در این مثال، store را با استفاده ازappStoreثبت کردیم.ما همچنین افکت ها را با appEffectsثبت کردیم.مرحله 8: از store در کامپوننت ToDo List استفاده کنید.برای استفاده از store در کامپوننت‌های خود، باید سرویسStoreرا تزریق کنید و اکشن ها را ارسال کنید. ما یک کامپوننت مستقلTodoListComponentداخل src/todo-list.component.tsبا فایل html در src/todo-list.component.html ایجاد خواهیم کرد.@Component({ standalone: true, selector: 'app-todo-list', imports: [NgFor, NgIf, AsyncPipe, JsonPipe], templateUrl: './todo-list.component.html' }) export class TodoListComponent { todos$: Observable<Todo[]>; isLoading$: Observable<boolean>; constructor(private store: Store<AppState>) { this.todos$ = this.store.select(todoSelector); this.isLoading$ = this.store.select(state => state.todo.loading); this.loadTodos(); } loadTodos() { this.store.dispatch(TodoActions.loadTodos()); } addTodo(index: number) { const todo: Todo = {id: index, description: 'New Todo', completed: false }; this.store.dispatch(TodoActions.addTodo({ todo })); } complete(todo: Todo) { this.store.dispatch(TodoActions.updateTodo({todo : {...todo, completed: true}})); } }در این مثال، کامپوننتی را تعریف می کنیم که از سرویسStoreبرای بارگذاری و نمایش کارهای انجام شده استفاده می کند. سرویس Storeرا تزریق می کنیم و ویژگیtodosرا از state با استفاده از متد select انتخاب می کنیم. ما همچنین سه متد برای ارسال اکشن های loadTodos, addTodoو updateTodo تعریف می کنیم. پایپ asyncبرای سابسکرایب کردن به $todosو نمایش لیست کارهای انجام شده استفاده می شود.مرحله 9: کامپوننت ToDo List را در کامپوننت اصلی ثبت کنید.@Component({ selector: 'my-app', standalone: true, imports: [ CommonModule, TodoListComponent ], template: ` <app-todo-list/> `, }) export class App { }اینTodoListComponentرا در آرایه imports اضافه کنید .تگ <app-todo-list/>را برای نمایش TodoListComponent اضافه کنید .نتیجهدر این راهنما، ما روند گام به گام پیاده سازی NGRX در یک برنامه Angular را طی کرده ایم. ما نحوه تعریف state، actions، reducers ، effects و نحوه استفاده از store را در کامپوننت ها دیدیم. با انجام این مراحل می توانید به راحتی با استفاده از NGRX حالت های برنامه خود را به صورت مقیاس پذیر و قابل پیش بینی مدیریت کنید.این مقاله برگردان شده یک مقاله معتبر درباره این موضوع است.برای دسترسی به مقاله منبع اینجا کلیک کنید.برای مشاهده پست های بیشتر و ارتباط با من از طریق لینکدین اینجا کلیک کنید.امیدوارم براتون مفید واقع شده باشه.