Bu sahifa hali tarjima qilinmagan

Tarjima qoshish uchun havola boyicha o'tib Pull Request oching (havolaga o'tish).

Standart til uchun tarkibni ko'rsatadi.

How to think in the effector paradigm

In fact, effector is not only about managing application state, but also about scalable building of your application logic. Effector does not limit you in how you write code, however, if you understand the following principles, it will be much easier to write code and think when you use effector:

  • Events are the description of your application, the foundation of everything.
  • Business logic and UI are different things; you should strive to separate the responsibility between data and its display.

Events — the foundation of everything

Every user interaction with your application is an event. An event doesn’t decide what should happen, it simply records the fact that something happened, for example: the user submitted a form - formSubmitted, the user clicked the refresh button - refreshButtonClicked, the user changed the search filter - searchFilterChanged, and so on. At the same time, events are not limited to user actions, they can also describe the logic of your model, for example: an explicit start of your model’s operation (micro-frontend or feature) - start, an error occurred - errorOccurred, and so on.

Don’t hesitate to create as many events as needed to fully describe the application’s actions, this makes it easier to see and track how your application works.

When designing new functionality, it’s easiest to start with events, since they are immediately visible in the interface.

Use meaningful names

Give events meaningful names. For example, if you need to load data upon some action, the event should be related to the action, not the implementation:

const fetchData = createEvent()
const appStarted = createEvent()

Separate business logic and UI

Effector allows you to separate the display (UI) and the logic of your application (business logic). All the logic of your application’s operation, as a rule, should be described separately from your UI, in a separate module, for example model.ts, and expose outward for the UI only what is needed for display or user interaction.

For example, when the formSubmitted event is triggered, you can call an effect to send data to the server, another effect to send analytics, and also display a notification to the user when event triggered:

const formSubmitted = createEvent();
const sendFormDataFx = createEffect(() => {});
const sendAnalyticsFx = createEffect(() => {});
const showNotificationFx = createEffect(() => {});
sample({
clock: formSubmitted,
target: [sendFormDataFx, sendAnalyticsFx, showNotificationFx],
});

At some point, your logic might change, and you decide to send analytics only after a successful form submission, and show the notification not only on form submission but also on error:

const formSubmitted = createEvent();
const sendFormDataFx = createEffect(() => {});
const sendAnalyticsFx = createEffect(() => {});
const showNotificationFx = createEffect(() => {});
sample({
clock: formSubmitted,
target: [sendFormDataFx, showNotificationFx],
});
sample({
clock: sendFormDataFx.doneData,
target: sendAnalyticsFx,
});
sample({
clock: sendFormDataFx.failData,
target: showNotificationFx,
});

Our application logic has changed, but the UI has not. Our UI doesn’t need to know which effects we are sending or what is changing, all our UI knows is that the refresh button was clicked and it needs to trigger the refreshButtonClicked event. Otherwise, if we mix logic and UI, we will have to change the code in the UI as well when the logic changes.

How does this look in a real application?

Let’s take GitHub and its repository functionality as an example. Every user action is an event:

repository action buttons in github

  • User starred/unstarred the repository - repoStarToggled
  • User changed the repository branch - repoBranchChanged
  • Repository file search string changed - repoFileSearchChanged
  • Repository was forked - repoForked

It’s much easier to build the entire application logic around events and the reactions to them. The UI simply reports an action, and its processing is part of the business logic.

A simplified example of the logic with the star button:

repo.model.ts
// event – the fact of an action
const repoStarToggled = createEvent();
// effects as an additional reaction to events
// (let's assume the effects return the updated value)
const starRepoFx = createEffect(() => {});
const unstarRepoFx = createEffect(() => {});
// application state
const $isRepoStarred = createStore(false);
const $repoStarsCount = createStore(0);
// star toggle logic
sample({
clock: repoStarToggled,
source: $isRepoStarred,
fn: (isRepoStarred) => !isRepoStarred,
target: $isRepoStarred,
});
// sending a request to the server when the star is toggled
sample({
clock: $isRepoStarred,
filter: (isRepoStarred) => isRepoStarred,
target: starRepoFx,
});
sample({
clock: $isRepoStarred,
filter: (isRepoStarred) => !isRepoStarred,
target: unstarRepoFx,
});
// update the counter
sample({
clock: [starRepoFx.doneData, unstarRepoFx.doneData],
target: $repoStarsCount,
});
Tarjima jamiyat tomonidan qollanilyapti

Ingliz tilidagi hujjatlar eng dolzarb hisoblanadi, chunki u effector guruhi tomonidan yozilgan va yangilanadi. Hujjatlarni boshqa tillarga tarjima qilish jamiyat tomonidan kuch va istaklar mavjud bo'lganda amalga oshiriladi.

Esda tutingki, tarjima qilingan maqolalar yangilanmasligi mumkin, shuning uchun eng aniq va dolzarb ma'lumot uchun hujjatlarning asl inglizcha versiyasidan foydalanishni tavsiya etamiz.

Hammualliflar