{"id":6895,"date":"2019-04-30T13:00:42","date_gmt":"2019-04-30T11:00:42","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=6895"},"modified":"2023-11-07T08:19:45","modified_gmt":"2023-11-07T07:19:45","slug":"sharepoint-framework-and-mobx-webpart-example","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/sharepoint-framework-and-mobx-webpart-example\/","title":{"rendered":"SharePoint Framework and MobX \u2013 WebPart example"},"content":{"rendered":"\n<p>We know <a href=\"https:\/\/sii.pl\/blog\/en\/sharepoint-framework-and-mobx-how-to-make-app-data-management-easier\/?category=hard-development&amp;tag=mobx-en,office-365-en,office-365-competency-center-en,sharepoint-en,sharepoint-framework-en,spfx-en\" target=\"_blank\" rel=\"noopener\">how MobX can make managing state of our SPFx app easier<\/a> and <a href=\"https:\/\/sii.pl\/blog\/en\/sharepoint-framework-and-mobx-basic-ideas-and-apis\/?category=hard-development&amp;tag=mobx-en,office-365-en,sharepoint-en,sharepoint-framework-en,spfx-en\" target=\"_blank\" rel=\"noopener\">what are its fundamentals<\/a>. So let\u2019s see how to put all that knowledge into practice.<\/p>\n\n\n\n<p>We\u2019re going to focus on example from <a href=\"https:\/\/sii.pl\/blog\/en\/sharepoint-framework-and-mobx-how-to-make-app-data-management-easier\/?category=hard-development&amp;tag=mobx-en,office-365-en,office-365-competency-center-en,sharepoint-en,sharepoint-framework-en,spfx-en\" target=\"_blank\" rel=\"noopener\">the first article<\/a>. Just for the record:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/01\/SPFx-MobX-1-Mockup-Office-365.png\" alt=\"\" class=\"wp-image-6868\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><em>A mockup of an example solution<\/em><\/p>\n\n\n\n<p>After creating basic SPFx WebPart, we can install MobX. In our case, we can use npm \u2013 we need two packages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.npmjs.com\/package\/mobx\" rel=\"nofollow\" >mobx<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.npmjs.com\/package\/mobx-react\" rel=\"nofollow\" >mobx-react<\/a><\/li>\n<\/ul>\n\n\n\n<p>And to make our lives easier \u2013 ready-to-use components from <a href=\"https:\/\/www.npmjs.com\/package\/office-ui-fabric-react\" rel=\"nofollow\" >Office UI Fabric<\/a>.<\/p>\n\n\n\n<p>With MobX onboard, we can create our store class. We\u2019re going to share some observables, so let\u2019s create actions as well.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nexport class ExampleStore {\n@observable public SelectedColor: string = '#f03333';\n@observable public SelectedIcon: string = 'FavoriteStar';\n@observable public SelectedItem: string = 'This is the first option';\n \n@action.bound\npublic updateColor(value: string): void {\nthis.SelectedColor = value;\n}\n \n@action.bound\npublic updateIcon(value: string): void {\nthis.SelectedIcon = value;\n}\n \n@action.bound\npublic updateItem(value: string): void {\nthis.SelectedItem = value;\n}\n}\n<\/pre><\/div>\n\n\n<p>We have to make sure, that our components share the same instance of the store, so let\u2019s create it in the main WebPart class and distribute it to the rest of elements.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nexport default class SpfxMobxExampleWebPart extends BaseClientSideWebPart&amp;lt;ispfxmobxexamplewebpartprops&amp;gt; {\nprivate store: ExampleStore = new ExampleStore();&amp;lt;\/ispfxmobxexamplewebpartprops&amp;gt;\n \npublic render(): void {\nconst element: React.ReactElement&amp;lt;imaincontainerprops&amp;gt; = React.createElement(\nMainContainer, { store: this.store });\nReactDom.render(element, this.domElement);\n}\n\u2026\n}\n<\/pre><\/div>\n\n\n<p>Useful tip for future. If few solutions or webparts are using MobX, they load it separately to the target site. The same situation happens when user add solution provided by another supplier. It can use MobX as well and every instance of MobX can interfere with other. We should always protect our solution against this type of issue. I recommend to use isolateGlobalState flag:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\tconfigure({ isolateGlobalState: true });\n<\/pre><\/div>\n\n\n<p>You can learn more about it <a href=\"https:\/\/github.com\/mobxjs\/mobx\/issues\/1082\" rel=\"nofollow\" >here<\/a>.<\/p>\n\n\n\n<p>It\u2019s time for our component structure.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Main Container\n<ul class=\"wp-block-list\">\n<li>Top Label<\/li>\n\n\n\n<li>Middle Container\n<ul class=\"wp-block-list\">\n<li>Dropdown #1<\/li>\n\n\n\n<li>Dropdown #2<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Bottom Container\n<ul class=\"wp-block-list\">\n<li>Left Column\n<ul class=\"wp-block-list\">\n<li>Row #1<\/li>\n\n\n\n<li>Row #2<\/li>\n\n\n\n<li>Row #3<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Right Column Image<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>We assumed that the row icon is connected with the top label. So let\u2019s look at \u2018click\u2019 handler of the first one.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n@autobind\nprivate onClick(event): void {\nthis.props.store.updateItem(this.props.text);\n}\n<\/pre><\/div>\n\n\n<p>And render of our main label.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n&lt;label classname=&quot;{styles.mainLabel}&quot;&gt;{this.props.store.SelectedItem}&lt;\/label&gt;\n<\/pre><\/div>\n\n\n<p>Click on the icon changes store\u2019s observable that is used by the top label. Yaay! How about some reactions?<\/p>\n\n\n\n<p>Rows suppose to make influence on the image column on the right. Let\u2019s say that selection of the item causes sending request to SharePoint list to get the picture source. It\u2019s a great opportunity to use MobX reactions.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nreaction(\n() =&gt; this.props.store.SelectedItem,\nasync selectedItem =&gt; {\nconst imageSrc: string = await ListService.getImage(selectedItem);\nthis.props.store.updateImageSrc(imageSrc);\n},\n{ fireImmediately: true }\n)\n<\/pre><\/div>\n\n\n<p>Our function reacts to the item changes \u2013 it triggers a service and updates the image source. You can learn more about reactions <a href=\"https:\/\/mobx.js.org\/refguide\/reaction.html\" rel=\"nofollow\" >here<\/a>.<\/p>\n\n\n\n<p>So, finally, we end up with our MobX based WebPart.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2019\/01\/SPFx-MobX-3-Clicking-Office-365.gif\" alt=\"\" class=\"wp-image-6900\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><em>Basic operations on our WebPart<\/em><\/p>\n\n\n\n<p>To sum up our article series:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>MobX is a library that make state management of SPFx app easier \u2013 it helps you share data between components<\/li>\n\n\n\n<li>It was created with the intention to use it with React<\/li>\n\n\n\n<li>Main elements of MobX based SPFx solution could be:\n<ul class=\"wp-block-list\">\n<li>the store class with observables, computed values and actions<\/li>\n\n\n\n<li>observer classes<\/li>\n\n\n\n<li>reactions<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;6895&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;6&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 6)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;SharePoint Framework and MobX \u2013 WebPart example&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 6)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>We know how MobX can make managing state of our SPFx app easier and what are its fundamentals. So let\u2019s &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/sharepoint-framework-and-mobx-webpart-example\/\">Continued<\/a><\/p>\n","protected":false},"author":546,"featured_media":25156,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":2,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[1345,1346,1446,1444,1445],"class_list":["post-6895","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-sharepoint-en","tag-office-365-en","tag-mobx-en","tag-sharepoint-framework-en","tag-spfx-en"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/10\/Porownanie-wydajnosci-mechanizmu-Qt-Signals-i-Slots-oraz-natywnej-implementacji-C.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/6895"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/546"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=6895"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/6895\/revisions"}],"predecessor-version":[{"id":25368,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/6895\/revisions\/25368"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/25156"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=6895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=6895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=6895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}