کتابخانه NGRX یک کتابخانه محبوب برای مدیریت state ها در برنامه های Angular است. این کتابخانه کمک می کند تا وضعیت یک برنامه را به روشی قابل پیش بینی و مقیاس پذیر مدیریت کنید. در این راهنما، فرآیند پیاده سازی NGRX را با ساختن یک اپلیکیشن کوچک Todo به صورت گام به گام طی خواهیم کرد.
در اینجا می توانید به کد کامل مراجعه کنید.
برای نصب 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
اولین قدم این است که مدل داده های خود را در store/todo.model.ts
را تعریف کنید.
export interface Todo { id: number | string; description: string; completed: boolean; }
در این مثال، interface Todo
را با برخی ویژگی ها تعریف می کنیم.
سرویس ما شامل سرویس 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ها استفاده می شود.
کاهنده ها یا 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 یک عمل خاص را انجام می دهد و یک حالت جدید را برمی گرداند.
افکتها سرویسهایی هستند که به اکشن ها گوش میدهند و اثرات جانبی مانند درخواستهای 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
را ارسال می کند.
اینترفیس در فایل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ها در برنامه استفاده می شود.
برای استفاده از 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
ثبت کردیم.
برای استفاده از 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
و نمایش لیست کارهای انجام شده استفاده می شود.
@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 حالت های برنامه خود را به صورت مقیاس پذیر و قابل پیش بینی مدیریت کنید.
این مقاله برگردان شده یک مقاله معتبر درباره این موضوع است.برای دسترسی به مقاله منبع اینجا کلیک کنید.
برای مشاهده پست های بیشتر و ارتباط با من از طریق لینکدین اینجا کلیک کنید.
امیدوارم براتون مفید واقع شده باشه.