﻿
{"id":27050,"date":"2024-06-23T01:43:32","date_gmt":"2024-06-23T01:43:32","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=27050"},"modified":"2024-06-23T01:43:32","modified_gmt":"2024-06-23T01:43:32","slug":"signal-store-ve-ngxs-state-managementta-esnekligi-artirma","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/signal-store-ve-ngxs-state-managementta-esnekligi-artirma\/","title":{"rendered":"Signal Store ve NGXS &#8211; State Management&#8217;ta Esnekli\u011fi Art\u0131rma"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Malumunuz, Angular mimarisinde <a href=\"https:\/\/www.gencayyildiz.com\/blog\/angular-16-signals-yapilanmasini-detayli-inceleyelim\/\" rel=\"noopener\" target=\"_blank\">signal<\/a> yap\u0131lanmas\u0131n\u0131n gelmesi ve kullan\u0131lmaya ba\u015flamas\u0131yla \u00f6zellikle state management&#8217;ta olmak \u00fczere farkl\u0131 davran\u0131\u015f f\u0131rsatlar\u0131 ortaya \u00e7\u0131km\u0131\u015f bulunmaktad\u0131r. Bunlardan en me\u015fhuru NgRx ekibi taraf\u0131ndan signal tabanl\u0131 state management i\u00e7in geli\u015ftirilmi\u015f olan <a href=\"https:\/\/ngrx.io\/guide\/signals\" rel=\"noopener\" target=\"_blank\">@ngrx\/signals<\/a> k\u00fct\u00fcphanesidir. Bu k\u00fct\u00fcphane, ihtiya\u00e7 noktalar\u0131nda olduk\u00e7a esnek ve etkili \u00e7\u00f6z\u00fcmler getirmekte ve bundan dolay\u0131 community taraf\u0131ndan geni\u015f \u00e7apta kabul g\u00f6rmektedir. \u00d6zellikle hem local hem de global state&#8217;leri y\u00f6netmek i\u00e7in ve store&#8217;u \u00f6l\u00e7eklendirmek yahut payla\u015f\u0131labilir k\u0131lmak i\u00e7in yard\u0131mc\u0131 olan ekstradan ara\u00e7lar sunmaktad\u0131r.<\/p>\n<p>Bunlar\u0131n d\u0131\u015f\u0131nda bu k\u00fct\u00fcphane ile ihtiya\u00e7lar\u0131m\u0131za g\u00f6re istedi\u011fimiz store&#8217;u uyarlayabilmemiz i\u00e7in bir tak\u0131m adapt\u00f6rler sunulmu\u015ftur. Misal olarak NGXS, kendi Signal Store implementasyonlar\u0131n\u0131 olu\u015fturmak yerine <code>@ngxs\/store<\/code> ile NgRx Signal Store ba\u011flant\u0131s\u0131n\u0131 sa\u011flayacak olan bir dizi yard\u0131mc\u0131 ara\u00e7 olu\u015fturmay\u0131 tercih etmi\u015ftir. Temel olarak NGXS store&#8217;a dayal\u0131 uygulamalar, NgRx Signal Store&#8217;u minimum \u00e7abayla entegre edebilmektedirler.<\/p>\n<h3>\u0130nceleme<\/h3>\n<p>\u015eimdi bir inceleme \u00fczerinden olay\u0131 pratiksel olarak ele alal\u0131m. Bir Angular uygulamas\u0131na \u00f6ncelikle <code>npm install @ngxs\/store @ngxs\/logger-plugin @ngxs\/devtools-plugin<\/code> talimat\u0131 e\u015fli\u011finde NGXS&#8217;i ekleyelim. Ard\u0131ndan <code>npm i @ngrx\/signals@18.0.0-rc.1<\/code> talimat\u0131 ile de NgRx&#8217;i kural\u0131m.<\/p>\n<p>\u015eimdi NGXS ile Signal Store aras\u0131nda bir k\u00f6pr\u00fc olu\u015fturabilmek i\u00e7in kodda k\u00fc\u00e7\u00fck bir \u00e7al\u0131\u015fma yap\u0131lmas\u0131 gerekmektedir. Bu \u00e7al\u0131\u015fma i\u00e7in NGXS&#8217;in sundu\u011fu a\u015fa\u011f\u0131daki iki fonksiyondan istifade edebiliriz;<\/p>\n<ul>\n<li><em>createSelectMap<\/em>, belirli state selector&#8217;lar\u0131n\u0131 daha rahat kullanabilmemizi sa\u011flayan bir metottur. Bu metot, selector&#8217;lar\u0131n map&#8217;lenmesini sa\u011flar ve component&#8217;lerde bu selector&#8217;lar\u0131n daha kolay bir \u015fekilde kullan\u0131lmas\u0131na yard\u0131mc\u0131 olur.<\/li>\n<li><em>createDispatchMap<\/em>, belirli aksiyonlar\u0131n daha rahat dispatch edilmesini sa\u011flar.<\/li>\n<\/ul>\n<p>\u0130lk olarak <code>withSelectors<\/code> adapt\u00f6r\u00fcn\u00fc olu\u015ftural\u0131m. Bu adapt\u00f6r, selector&#8217;lar\u0131n computed edilmi\u015f signal&#8217;lar\u0131n\u0131 olu\u015fturacakt\u0131r. Bunun i\u00e7in de a\u015fa\u011f\u0131daki gibi <code>withComputed<\/code> fonksiyonundan istifade edece\u011fiz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nimport { SelectorMap, createSelectMap } from &quot;@ngxs\/store&quot;;\r\nimport { signalStoreFeature, withComputed } from &quot;@ngrx\/signals&quot;;\r\n\r\nexport function withSelectors&lt;T extends SelectorMap&gt;(selectorMap: T) {\r\n    return signalStoreFeature(withComputed(() =&gt; createSelectMap(selectorMap)))\r\n}\r\n<\/pre>\n<\/div>\n<p>Bunu a\u015fa\u011f\u0131daki gibi store olarak yap\u0131land\u0131rabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nimport { signalStore } from &quot;@ngrx\/signals&quot;;\r\nimport { withSelectors } from &quot;..\/shared\/ngxs.utils&quot;;\r\nimport { CounterSelector } from &quot;..\/selectors\/counter.selector&quot;;\r\n\r\nexport const CounterStore = signalStore(\r\n    withSelectors({\r\n        counter: CounterSelector.getCount\r\n    })\r\n);\r\n<\/pre>\n<\/div>\n<p>Benzer mant\u0131kla action&#8217;lar\u0131 da g\u00f6ndermemizi sa\u011flayacak olan <code>withActions<\/code> adapt\u00f6r\u00fcn\u00fc olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport function withActions&lt;T extends ActionMap&gt;(actionMap: T) {\r\n    return signalStoreFeature(withMethods(() =&gt; createDispatchMap(actionMap)))\r\n}\r\n<\/pre>\n<\/div>\n<p>Bu adapt\u00f6r, <code>createDispatchMap<\/code>&#8216;ten bir dispatcher haritas\u0131 alan ve bunu Signal Store fonksiyonuna d\u00f6n\u00fc\u015ft\u00fcren <code>withMethods<\/code> fonksiyonunu kullanmaktad\u0131r.<\/p>\n<p>Bunu da biraz \u00f6nce olu\u015fturdu\u011fumuz store i\u00e7erisinde a\u015fa\u011f\u0131daki gibi yap\u0131land\u0131rabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nexport const CounterStore = signalStore(\r\n    withSelectors({\r\n        counter: CounterSelector.getCount\r\n    }),\r\n    withActions({\r\n        increment: Increment,\r\n        decrement: Decrement\r\n    })\r\n);\r\n<\/pre>\n<\/div>\n<p>Ve bu store&#8217;u nihai olarak component&#8217;te a\u015fa\u011f\u0131daki gibi kullanabiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nimport { Component, inject } from '@angular\/core';\r\nimport { Decrement, Increment } from '..\/..\/actions\/counter.actions';\r\nimport { CounterSelector } from '..\/..\/selectors\/counter.selector';\r\nimport { CounterStore } from '..\/..\/stores\/counter.store';\r\nimport { AComponent } from '..\/a\/a.component';\r\n\r\n@Component({\r\n  selector: 'app-counter',\r\n  standalone: true,\r\n  imports: &#x5B;AComponent],\r\n  providers: &#x5B;CounterStore],\r\n  template: `\r\n    &lt;h3&gt;NGXS Counter Example&lt;\/h3&gt;\r\n    &lt;!-- &lt;h2&gt;{{count$() }}&lt;\/h2&gt; --&gt;\r\n     &lt;h2&gt;{{counterStore.counter()}}&lt;\/h2&gt;\r\n    &lt;button (click)=&quot;increment()&quot;&gt;Increment&lt;\/button&gt;\r\n    &lt;button (click)=&quot;decrement()&quot;&gt;Decrement&lt;\/button&gt;\r\n\r\n    &lt;hr&gt;\r\n    &lt;app-a&gt;&lt;\/app-a&gt;\r\n  `\r\n})\r\nexport class CounterComponent {\r\n  readonly counterStore = inject(CounterStore);\r\n\r\n  increment() {\r\n    this.counterStore.increment();\r\n  }\r\n\r\n  decrement() {\r\n    this.counterStore.decrement();\r\n  }\r\n\r\n\r\n  \/\/#region NGXS State Management\r\n\r\n  \/\/ count$ = this.store.selectSignal(CounterSelector.getCount);\r\n\r\n  \/\/ constructor(private store: Store) {\r\n  \/\/   store.select(CounterSelector.getCount).subscribe(d =&gt; console.log(d));\r\n  \/\/ }\r\n\r\n  \/\/ increment() {\r\n  \/\/   this.store.dispatch(new Increment())\r\n  \/\/   this.counterStore\r\n  \/\/ }\r\n\r\n  \/\/ decrement() {\r\n  \/\/   this.store.dispatch(new Decrement());\r\n  \/\/ }\r\n\r\n  \/\/#endregion\r\n}\r\n<\/pre>\n<\/div>\n<p>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere \u00f6z\u00fcnde <code>signalStoreFeature<\/code> fonksiyonu arac\u0131l\u0131\u011f\u0131yla yapt\u0131\u011f\u0131m\u0131z \u00e7al\u0131\u015fmalar neticesinde NGXS&#8217;i geni\u015fleterek Signal Store ile uyumlu hale getirmi\u015f bulunuyor ve entegrasyonu sa\u011flam\u0131\u015f oluyoruz.<\/p>\n<p>Malum ki Angular&#8217;\u0131n signal&#8217;ler \u00fczerine olan ivmesi onlarca harici k\u00fct\u00fcphanede uyum \u00e7al\u0131\u015fmas\u0131n\u0131n yap\u0131laca\u011f\u0131n\u0131 g\u00f6stermektedir. En az\u0131ndan bizler bu i\u00e7eri\u011fimizde NGXS ile bu uyumun manuel olarak nas\u0131l sa\u011flanabilece\u011fini incelemi\u015f oluyoruz.<\/p>\n<p>Konuya daha iyi hakimiyet sa\u011flayabilmek i\u00e7in i\u00e7erikle uyumlu \u015fekilde geli\u015ftirmi\u015f oldu\u011fum a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fmaya g\u00f6z atman\u0131zda fayda g\u00f6rmekteyim.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/signal-store-example-with-ngxs\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/signal-store-example-with-ngxs<\/a><\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Malumunuz, Angular mimarisinde signal yap\u0131lanmas\u0131n\u0131n gelmesi ve kullan\u0131lmaya ba\u015flamas\u0131yla \u00f6zellikle state management&#8217;ta olmak \u00fczere farkl\u0131 davran\u0131\u015f f\u0131rsatlar\u0131 ortaya \u00e7\u0131km\u0131\u015f bulunmaktad\u0131r. Bunlardan en me\u015fhuru NgRx ekibi taraf\u0131ndan signal tabanl\u0131 state management i\u00e7in geli\u015ftirilmi\u015f olan&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26698,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2420,5061],"tags":[2156,5066,5065,5068,5067,4495],"class_list":["post-27050","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular","category-angular-18","tag-angular","tag-angular-ngxs","tag-angular-signal-store","tag-angular-state-management","tag-ngxs","tag-state-management"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27050","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=27050"}],"version-history":[{"count":4,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27050\/revisions"}],"predecessor-version":[{"id":27056,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27050\/revisions\/27056"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26698"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=27050"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=27050"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=27050"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}