برنامه نویسی

مدیریت دولت اتمی چیست – خودتان بسازید

ایالت کجا زندگی می کند؟

پاسخ سرراست نیست. توسعه دهندگان React معمولاً از دو استراتژی برای ساختاربندی وضعیت برنامه استفاده می کنند: حالت جزء (با استفاده از useState) و ذخیره جهانی (با استفاده از Redux). وضعیت می تواند به طور نزدیک به کامپوننت مرتبط باشد یا در فروشگاه Redux ذخیره شود، به این معنی که نزدیک به منبع است و نمی تواند به طور مستقل ایجاد شود.

آیا تا به حال خود را در موقعیتی قرار داده اید که بخواهید از قلاب useState استفاده کنید، اما به شیء حالت خود نیز ارجاع دهید؟ اینجاست که مدل مدیریت حالت اتمی وارد می شود.

اتم ها

مدیریت حالت اتمی شامل استفاده از اتم ها به عنوان یک مخزن مرکزی برای مدیریت دولتی است. می توان آن را به عنوان یک نسخه ارتقا یافته از قلاب useState دید که امکان اشتراک گذاری حالت بین اجزا را فراهم می کند. این رویکرد مزایای هر دو حالت جزء و الگوهای فروشگاه جهانی را ترکیب می کند. اتم ها به طور هدفمند طراحی شده اند تا یک مقدار منفرد را نگه دارند.

همانطور که در مثال زیر نشان داده شده است، نوشتار کوتاه است و برای اشتراک گذاری بین اجزاء آسان است.

// Example from jotai.org
const animeAtom = atom(animeAtom);

const Header = () => {
  const [anime, setAnime] = useAtom(animeAtom)
  ...
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

همانطور که در مثال بالا می بینید، مدل مدیریت حالت اتمی کد دیگ بخار را در مقایسه با رویکردهایی مانند الگوی شار کاهش می دهد و بسیار شبیه به قلاب useState React است.

TL;DR از تکنیک های مدیریت حالت اتمی برای دستیابی به انعطاف پذیری بهتر در سازماندهی مدیریت حالت برنامه استفاده کنید.

خودتان را از ابتدا بسازید.

قبل از ادامه، می توانید پروژه را در github بررسی کنید. این پیاده سازی برای اهداف یادگیری است، برای استفاده در تولید، Jotai یا Recoil را بررسی کنید.

Atom Creators / اجرای کارخانه

let atomId = 0;

function atomFactory(payload) {
  const atom = {};

  const subscribers = new Map();

  let subscriberIds = 0;

  const key = atomId++;

  // This function returns the current value
  atom.get = function () {
    return atom.value;
  };

  // sets value and notify to subscribers
  atom.set = function (value) {
    atom.value = value;
    notify(value);
  };

  // notifier function to notify value
  function notify(value) {
    subscribers.forEach((subscriber) => {
      subscriber(value);
    });
  }

  // subscribe to changes; returns unsubscribe fn
  atom.subscribe = function (fn, initialId) {
    const id = initialId ?? (subscriberIds += 1);

    subscribers.set(id, fn);

    return () => void subscribers.delete(id);
  };

  // actual atom value
  atom.value = payload;

  return atom;
}

export { atomFactory as atom }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این یک پیاده سازی بسیار اساسی از کارخانه اتم است که یک شی اتم را برمی گرداند.

// atom returned by factory fn

{
    get: () => void
    set: (value: any) => void
    subscribe: () => (() => void)
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پیاده سازی قلاب استفاده از اتم

export function useAtom(atom) {
  const [state, setState] = useState(atom.get());

  useEffect(() => {
    // subscribe on mount and sets local state with new value (used for sync atom to reacts state)
    const unSubscribe = atom.subscribe(setState);

    // unsubscribe on unmount
    return () => unSubscribe();
  }, [atom]);

  // just setter function.
  const setAtomValue = useCallback((value) => atom.set(value), [atom]);

  return [state, setAtomValue];
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اوهومممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممممم.

useAtomValue و useAtomSetter Implementation

در اینجا ما قلاب های useAtom را به دو قسمت تقسیم می کنیم.

// useAtomValue
export function useAtomValue(atom) {
  const [state, setState] = useState(atom.get());

  useEffect(() => {
    const unSubscribe = atom.subscribe(setState);
    return () => unSubscribe();
  }, [atom]);

  return state;
}

// useAtomSetter
export function useAtomSetter(atom) {
  return useCallback((value) => atom.set(value), [atom]);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده مجدد از اتم هوک

export function useAtom(atom) {
  return [useAtomValue(atom), useAtomSetter(atom)];
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

استفاده

همان جوتای است

// Example from jotai.org
const animeAtom = atom('bleach');

const Header = () => {
  const [anime, setAnime] = useAtom(animeAtom)
  ...
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پیاده سازی اتم مشتق شده

// refactored atom factory fn
function atomFactory(payload) {
  const atom = {};

  const subscribers = new Map();

  let subscriberIds = 0;

  const key = atomId++;

  // getAtom function used to subscribe to another atom (for derived state)
  atom.getAtom = function (prevAtom) {
    prevAtom.subscribe(() => {
      if (payload instanceof Function) {
        atom.value = payload(atom.getAtom);
        notify(atom.value);
      }
    }, `atom_${key}`);

    return prevAtom.get();
  };

  atom.get = function () {
    return atom.value;
  };

  atom.set = function (value) {
    atom.value = value;
    notify(value);
  };

  function notify(value) {
    subscribers.forEach((subscriber) => {
      subscriber(value);
    });
  }

  atom.subscribe = function (fn, initialId) {
    const id = initialId ?? (subscriberIds += 1);

    subscribers.set(id, fn);

    return () => void subscribers.delete(id);
  };

  // check if the payload is a function (derived atom) or normal atom
  if (payload instanceof Function) {
    atom.value = payload(atom.getAtom);
  } else {
    atom.value = payload;
  }

  return atom;
}

export { atomFactory as atom }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

useAtom به همان صورت باقی خواهد ماند.

مثال اتم مشتق شده

import { atom, useAtom, useAtomValue } from './lib';

const priceAtom = createAtom(15);

const discountAtom = createAtom(10);

const discountedPriceAtom = createAtom((get) => {
    return (get(priceAtom) / 100) * get(discountAtom);
});

const Component = () => {
  const [price, setPrice] = useAtom(priceAtom);

  const discountedPrice = useAtomValue(discountedPriceAtom);
  ...
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

جایزه: پلاگین atomWithLocalStorage

import { atom } from "./lib";

export function atomWithLocalStorage(key, payload) {
  //Create new atom
  const newAtom = atom(payload);

  // check value exists in localstorage or not
  const prevVal = JSON.parse(localStorage.getItem(key) || "null");

  if (prevVal) {
    // if the value exists in localstorage sets to atom
    newAtom.set(prevVal.data);
  }

  // subscribe to changes and set value in localstorage
  newAtom.subscribe((val) =>
    localStorage.setItem(key, JSON.stringify({ data: val }))
  );

  return newAtom;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا