استفاده از چند مشاهده گر

در صورتی که برنامه ای در مقیاس بزرگ دارید، یا میخواهید استیت بخش های مختلف اپ خود را به صورت جداگانه مدیریت کنید، میتوانید از کلاس Observer نمونه هایی به همین منظور ایجاد کنید.

برای این منظور باید کلاس observer را از rosma ایمپورت کرده با و استفاده از کلید واژه new یک نمونه از آن بسازید.

import { Observer } from 'rosma'; const myObserver = new Observer();
import { Observer } from 'rosma'; const myObserver = new Observer();

توجه داشته باشد که اگر برای هر استیت مقادیر اولیه ای در تظر دارید، میتوانید آن مقادیر را به constructor کلاس observer ارسال کنید.

import { Observer } from 'rosma'; const myObserver = new Observer({ foo: 'bar' }); console.log(myObserver.state.foo); //"bar"
import { Observer } from 'rosma'; type State = { foo: string; }; const myObserver = new Observer<State>({ foo: 'bar' }); console.log(myObserver.state.foo); //"bar"

همچنین برای اینکه هوک useObserver از observer شخصی شما استفاده کند میتوانید observer خود را به این صورت به useObserver ارسال کنید.

import { Observer, useObserver } from 'rosma'; const myObserver = new Observer({ random: 'Click Generate to generate random number', }); function App() { const { random, setRandom } = useObserver(myObserver); return ( <> <p>{random}</p> <button onClick={generate}>Generate</button> </> ); function generate() { setRandom(Math.random() * 1000); } }
import { Observer, useObserver } from 'rosma'; type State = { random: string | number; }; const myObserver = new Observer<State>({ random: 'Click Generate to generate random number', }); function App() { const { random, setRandom } = useObserver<State>(myObserver); return ( <> <p>{random}</p> <button onClick={generate}>Generate</button> </> ); function generate() { setRandom(Math.random() * 1000); } }

Click Generate to generate random number

سفارشی کردن هوک useObserver

برای اینکه پاس دادن observer به هوک useObserver را در سرتاسر آپ خود تکرار نکنید میتوانید مانند مثال زیر یکبار hook شخصی خود را اکسپورت کرده و در همه جای آپ آن را ایمپورت کنید.

import { Observer, useObserver } from 'rosma'; const initialUIState = { mustShowSidebar: true }; const initialAuthState = { user: undefined, token: undefined }; const initialDataState = { posts: [], users: [] }; export const UIObserver = new Observer(initialUIState); export const authObserver = new Observer(initialAuthState); export const dataObserver = new Observer(initialDataState); export function useUIObserver() { return useObserver(UIObserver); } export function useAuthObserver() { return useObserver(authObserver); } export function useDataObserver() { return useObserver(dataObserver); }
import { Observer, useObserver } from 'rosma'; type UIState = { mustShowSidebar: boolean; }; type AuthState = { user?: User; token?: string; }; type DataState = { posts: Post[]; users: User[]; }; const initialUIState: UIState = { mustShowSidebar: true }; const initialAuthState: AuthState = { user: undefined, token: undefined }; const initialDataState: DataState = { posts: [], users: [] }; export const UIObserver = new Observer<UIState>(initialUIState); export const authObserver = new Observer<AuthState>(initialAuthState); export const dataObserver = new Observer<DataState>(initialDataState); export function useUIObserver() { return useObserver<UIState>(UIObserver); } export function useAuthObserver() { return useObserver<AuthState>(authObserver); } export function useDataObserver() { return useObserver<DataState>(dataObserver); }

این مثال نشان می دهد که چگونه می توان چندین نمونه از کلاس Observer را با استیت های اولیه مختلف با استفاده از کلمه کلیدی new ایجاد کرد. سه نمونه از مشاهده‌گر با نام‌های UIObserver، authObserver و dataObserver ایجاد می‌شوند. هر نمونه مقدار اولیه متفاوتی دارد که هر کدام در object جداگانه ای تعریف شده اند .

علاوه بر ایجاد مشاهده گر ها، ما سه تابع، useUIObserver، useAuthObserver و useDataObserver را export می کنیم که از هوک useObserver برای دسترسی به observer های مربوطه در سراسر برنامه استفاده می کنند.

این رویکرد می تواند به مدیریت وضعیت بخش های مختلف یک برنامه به طور جداگانه کمک کند. با داشتن observer های جداگانه، می توانید به راحتی وضعیت یک قسمت خاص از برنامه را بدون تأثیر بر وضعیت سایر قسمت ها تغییر دهید.

جداسازی مشاهده گر ها

برای خوانا تر شدن کد بهتر است همانند مثال زیر، observer های مربوط به هر بخش از آپ خود را در یک فایل جداگانه نگهداری کنید:

بخش UI

src/observers/ui/observer.ts

import { Observer, useObserver } from 'rosma'; const initialUIState = { mustShowSidebar: true }; export const UIObserver = new Observer(initialUIState); export function useUIObserver() { return useObserver(UIObserver); }
import { Observer, useObserver } from 'rosma'; type UIState = { mustShowSidebar: boolean; }; const initialUIState: UIState = { mustShowSidebar: true }; export const UIObserver = new Observer<UIState>(initialUIState); export function useUIObserver() { return useObserver<UIState>(UIObserver); }

src/observers/ui/actions.ts

import { UIObserver } from './observer'; export function toggleSidebar() { UIObserver.set({ mustShowSidebar: !UIObserver.state.mustShowSidebar }); }
import { UIObserver } from './observer'; export function toggleSidebar() { UIObserver.set({ mustShowSidebar: !UIObserver.state.mustShowSidebar }); }

بخش احراز هویت

src/observers/auth/observer.ts

import { Observer, useObserver } from 'rosma'; const initialAuthState = { user: undefined, token: undefined }; export const authObserver = new Observer(initialAuthState); export function useAuthObserver() { return useObserver(authObserver); }
import { Observer, useObserver } from 'rosma'; type AuthState = { user?: User; token?: string; }; const initialAuthState: AuthState = { user: undefined, token: undefined }; export const authObserver = new Observer<AuthState>(initialAuthState); export function useAuthObserver() { return useObserver<AuthState>(authObserver); }

src/observers/auth/actions.ts

import { authObserver } from './observer'; export function login({ username, password }) { // logics for login authObserver.set({ user, token }); } export function logout() { // logics for logout authObserver.set({ user: undefined, token: undefined }); }
import { authObserver } from './observer'; export function login({ username, password }) { // logics for login authObserver.set({ user, token }); } export function logout() { // logics for logout authObserver.set({ user: undefined, token: undefined }); }

بخش دیتا

src/observers/data/observer.ts

import { Observer, useObserver } from 'rosma'; const initialDataState = { posts: [], users: [] }; export const dataObserver = new Observer(initialDataState); export function useDataObserver() { return useObserver(dataObserver); }
import { Observer, useObserver } from 'rosma'; type DataState = { posts: Post[]; users: User[]; }; const initialDataState: DataState = { posts: [], users: [] }; export const dataObserver = new Observer<DataState>(initialDataState); export function useDataObserver() { return useObserver<DataState>(dataObserver); }

src/observers/data/actions.ts

import { dataObserver } from './observer'; export function getPosts() { // logics for getting posts dataObserver.set({ posts }); } export function getUsers() { // logics for getting users dataObserver.set({ users }); }
import { dataObserver } from './observer'; export function getPosts() { // logics for getting posts dataObserver.set({ posts }); } export function getUsers() { // logics for getting users dataObserver.set({ users }); }

توجه: این مثال به منظور ارائه مفهومی از نحوه مدیریت وضعیت در یک برنامه ارائه شده است و فقط جنبه توضیحی دارد. به عنوان مثال، در بخش دیتا ، توصیه می‌شود از کتابخانه‌های تخصصی‌تری مانند react-query برای گرفتن و cache کردن داده‌ها استفاده کنید.

کلید واژه ها: رزما, ری اکت, مشاهده‌گر, useObserver, چند مشاهده گر, مشاهده گر سفارشی

قبلی: کلاس مشاهده گر

بعدی: نظارت بر تغییرات استیت