Working with atoms in mobx

The mobx library has a very interesting primitive atom, which is created via createAtom. With its help, you can create very interesting constructions and build almost the entire architecture of the application. What does the documentation tell us: `createAtom` {🚀} Usage: `createAtom(name, onBecomeObserved?, onBecomeUnobserved?)` Creates your own observable data structure and hooks it up to MobX. Used internally by all observable data types. Atom exposes two `report` methods to notify MobX with when: - `reportObserved()`: the atom has become observed, and should be considered part of the dependency tree of the current derivation. - `reportChanged()`: the atom has changed, and all derivations depending on it should be invalidated. Let’s wrap it a little so that it will be more convenient to use it in the future. ...

May 18, 2023 · 3 min · 445 words · lexich

Asynchronous pagination

Today I would like to tell you a little about my own development https://github.com/lexich/async-paginator This is a small library that allows you to process data collections using asynchronous iterators. At the same time, flexible configuration of the number of tasks to be started simultaneously is available (you can start all at once or split into groups). import { paginatorUnordered, paginator } from 'async-paginator'; const sleep = (delay: number) => new Promise<void>((resolve) => setTimeout(resolve, delay)); // for ordering use `paginator` instead of paginatorUnordered const paginate = paginatorUnordered([1, 2, 3, 4, 5, 6, 7, 8], async (num) => { if (num % 2 === 0) { await sleep(10); // timeout 10ms } return num * 10; }, { offset: 1, chunks: 2, mode: 'chunks', }); const result: number[] = []; for await (const item of paginate) { if (!(item instanceof PaginationAsyncError)) { result.push(item.data); } } console.log("RESULT: ", result); // RESULT: [30, 20, 50, 40, 70, 60, 80]

May 17, 2023 · 1 min · 155 words · lexich

Branded types in typescript

Today I want to talk about branded types in typescript. To begin with, let’s imagine that we have a function for currency conversion. const usdToEur = (usdAmount: number, rate = 0.92) => usdAmount * rate; usdToEur(100); // === 92 eur Let’s improve it a little by introducing the types USD and EUR, so that not only the name of the function and the comments to it tell us about its purpose. type USD = number; type EUR = number; const usdToEur = (usdAmount: USD, rate = 0.92): EUR => usdAmount * rate; usdToEur(100); // === 92 eur It has become much better, but in fact nothing has changed, because we can also pass any number and the newly introduced types do not protect us from error. And here branded types come to our aid. The point is that we mix additional fields into the type description, which in fact (at runtime) do not exist, but at the same time typescript checks them. ...

May 15, 2023 · 2 min · 249 words · lexich

Migration in React from Context API to Mobx Part 2

Continuing yesterday’s topic about migration to mobx, the question reasonably arises, why migrate to anything at all, if there is redux, context api, useReducer and all sorts of similar solutions on which React development is now built. export const AppContext = createContext({}); export const AppContextProvider: FC = ({ children }) => { const [user, setUser] = useState<IUser>(undefined); const [profile, setProfile] = useState<IProfile>(undefined); const setUserId = (id: string) => loadUser(id).then(setUser); useEffect(() => { if (user) { loadProfile(user).then(setProfile); } else { setProfile(undefined); } }, [user]); return ( <AppContext.Provider values={{ user, profile, setUserId }}> {children} </AppContext.Provider>); } const Component: FC = () => { const { profile } = useContext(AppContext); return <div>{profile.content}</div> } Let’s imagine a virtual example that is quite simple to find in many projects. What’s wrong with it? Let’s do a thought experiment. We have a component that displays profile. How many times will our component re-render when we call setUserId. The first re-render will be on setUser, then useEffect will be called. I would never use it for state management. Next, setProfile and this is the second re-render. The same behavior will be in every component that uses this context. And suboptimality is only half the trouble, but if, for example, we want a small test to check how it all works… I don’t even want to think about it and move to the camp of those who don’t write tests and only talk about them at interviews. ...

May 12, 2023 · 2 min · 407 words · lexich

Migrating to React with Context API in Mobx Part 1

There are three things you can do endlessly in life: watch fire burn, watch water flow, and watch me try to persuade you to rewrite your React application with Context API to something more functional, on which you can build a normal application architecture. Lately, I’ve been choosing mobx more and more often, so let’s talk about it today. So what to do if the application is already written, but you need to start somewhere? ...

May 11, 2023 · 2 min · 399 words · lexich