MobX State Tree (MST) is a JavaScript state management library that offers a simple and straightforward way of modeling the state of your application.
It employs a tree-based structure to illustrate the relationships between different elements of the state. The tree consists of mutable and strictly protected objects with run-time type information.
In MST, you define the structure and behavior of your application state using models.
Creating Model
Models are similar to classes, but instead of using instance methods, you define the actions that alter the state. Actions can be either synchronous or asynchronous and can be combined to create complex state changes.
You can simply create a model types.model
.
To employs run-time type information, we have types
in MST. Providing the wrong type will make MST throw an error. For detailed information about MST type
please visit here.
Asynchronous actions
In MobX State Tree, the concepts of “yield” and “flow” pertain to managing asynchronous computations and handling side effects.
Asynchronous actions are best written using flow
and generators
. They always return a promise and work same as async/await.
An action in MST can useyield
to indicate that it can be paused and resumed at a later time, such as when performing asynchronous tasks like making API calls.
The flow
decorator is applied to functions that are intended to be used in MST actions. When a generator function is decorated with flow
the use of yield
statements becomes possible within the function, allowing for the execution of asynchronous tasks and their interruption as required.
flow
automatically wraps the generator function in a “reaction” that tracks dependencies and updates the state tree as necessary.
By using these concepts, developers can express asynchronous logic and handle side effects in a manner that is more manageable, easy to understand, and testable, compared to using traditional async/await or callbacks.
Here is an example of code snippet of FAQ store:
[JavaScript] const Faq = types.model(“Faq”, { isLoading: false, faqDetails: types.map(faq), … offset: 0 }).actions(self => { const getFaqQuestions = flow( function* getFaqQuestions(isInitialRequest) { try { self.isLoading = true; if (!isInitialRequest) { self.offset += 10; } else { self.offset = 0; } const result = yield appSyncDataFetch< QueryResultForFaqQuestions >(getFaqQuestionQuery, { limit: LIMIT, offset: self.offset }); log.info( `getFAQs Api completed successfully` ); const { items } = result.data.getFAQs; const faqQuestions: { answer: string; question: string }[] = []; items.forEach((item) => { item.questions.forEach((question) => { faqQuestions.push(question); }); }) const faqItems = [{ category: FAQ, questions: faqQuestions }]; onFetchSuccess(faqItems, isInitialRequest); } catch (error) { log.error(`getFAQs Api failed Error: ${error}`); self.error = error; } finally { self.isLoading = false; } }); return getFaqQuestions, }); [JavaScript]Thanks for the read 😊! Please don’t forget to provide any suggestion/feedback.