[{"data":1,"prerenderedAt":690},["ShallowReactive",2],{"blog-\u002Fpl\u002Fblog\u002F2026\u002Fosiem-ifow-i-jedna-mapa":3,"blog-project-\u002Fpl\u002Fblog\u002F2026\u002Fosiem-ifow-i-jedna-mapa":679},{"id":4,"title":5,"art":6,"body":7,"date":675,"description":676,"draft":677,"extension":678,"image":679,"kind":680,"meta":681,"navigation":132,"ogImage":682,"path":683,"project":679,"seo":684,"slug":679,"stem":685,"tags":686,"__hash__":689},"blog_pl\u002Fpl\u002Fblog\u002F2026\u002Fosiem-ifow-i-jedna-mapa.md","Osiem ifów i jedna mapa","\u002Fart\u002Fblog\u002Fosiem-ifow.svg",{"type":8,"value":9,"toc":668},"minimark",[10,19,24,27,320,323,327,330,432,446,449,453,456,459,524,602,609,613,616,639,650,654,664],[11,12,13,14,18],"p",{},"W code review trafiłem na funkcję, która obsługiwała menu akcji przy wierszu tabeli. Każda akcja otwierała swoje okno dialogowe, a funkcja miała osiem bloków ",[15,16,17],"code",{},"if"," – jeden pod drugim, prawie identycznych. Kod działał, ale zaciekawiło mnie, czy da się go zapisać krócej. Sytuacja jest prawdziwa, ale kod poniżej to przykład – nazwy i dane zmieniłem na listę zamówień w panelu sklepu.",[20,21,23],"h2",{"id":22},"punkt-wyjścia","Punkt wyjścia",[11,25,26],{},"Każde okno ma swoją zmienną. Gdy zmienna dostaje zamówienie, okno się otwiera:",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-js shiki shiki-themes github-light github-dark","const refundTarget = ref(null)\nconst cancelTarget = ref(null)\nconst shipTarget = ref(null)\nconst addressTarget = ref(null)\n\u002F\u002F … i tak dalej, osiem zmiennych\n\nfunction handleAction(action, close) {\n  if (action.key === 'refund') {\n    refundTarget.value = props.order\n  }\n  if (action.key === 'cancel') {\n    cancelTarget.value = props.order\n  }\n  if (action.key === 'ship') {\n    shipTarget.value = props.order\n  }\n  if (action.key === 'change_address') {\n    addressTarget.value = props.order\n  }\n  \u002F\u002F … jeszcze cztery takie bloki\n  if (typeof close === 'function') close()\n}\n","js","",[15,35,36,66,84,102,120,127,134,158,176,188,194,208,218,223,237,247,252,266,276,281,287,314],{"__ignoreMap":33},[37,38,41,45,49,52,56,60,63],"span",{"class":39,"line":40},"line",1,[37,42,44],{"class":43},"szBVR","const",[37,46,48],{"class":47},"sj4cs"," refundTarget",[37,50,51],{"class":43}," =",[37,53,55],{"class":54},"sScJk"," ref",[37,57,59],{"class":58},"sVt8B","(",[37,61,62],{"class":47},"null",[37,64,65],{"class":58},")\n",[37,67,69,71,74,76,78,80,82],{"class":39,"line":68},2,[37,70,44],{"class":43},[37,72,73],{"class":47}," cancelTarget",[37,75,51],{"class":43},[37,77,55],{"class":54},[37,79,59],{"class":58},[37,81,62],{"class":47},[37,83,65],{"class":58},[37,85,87,89,92,94,96,98,100],{"class":39,"line":86},3,[37,88,44],{"class":43},[37,90,91],{"class":47}," shipTarget",[37,93,51],{"class":43},[37,95,55],{"class":54},[37,97,59],{"class":58},[37,99,62],{"class":47},[37,101,65],{"class":58},[37,103,105,107,110,112,114,116,118],{"class":39,"line":104},4,[37,106,44],{"class":43},[37,108,109],{"class":47}," addressTarget",[37,111,51],{"class":43},[37,113,55],{"class":54},[37,115,59],{"class":58},[37,117,62],{"class":47},[37,119,65],{"class":58},[37,121,123],{"class":39,"line":122},5,[37,124,126],{"class":125},"sJ8bj","\u002F\u002F … i tak dalej, osiem zmiennych\n",[37,128,130],{"class":39,"line":129},6,[37,131,133],{"emptyLinePlaceholder":132},true,"\n",[37,135,137,140,143,145,149,152,155],{"class":39,"line":136},7,[37,138,139],{"class":43},"function",[37,141,142],{"class":54}," handleAction",[37,144,59],{"class":58},[37,146,148],{"class":147},"s4XuR","action",[37,150,151],{"class":58},", ",[37,153,154],{"class":147},"close",[37,156,157],{"class":58},") {\n",[37,159,161,164,167,170,174],{"class":39,"line":160},8,[37,162,163],{"class":43},"  if",[37,165,166],{"class":58}," (action.key ",[37,168,169],{"class":43},"===",[37,171,173],{"class":172},"sZZnC"," 'refund'",[37,175,157],{"class":58},[37,177,179,182,185],{"class":39,"line":178},9,[37,180,181],{"class":58},"    refundTarget.value ",[37,183,184],{"class":43},"=",[37,186,187],{"class":58}," props.order\n",[37,189,191],{"class":39,"line":190},10,[37,192,193],{"class":58},"  }\n",[37,195,197,199,201,203,206],{"class":39,"line":196},11,[37,198,163],{"class":43},[37,200,166],{"class":58},[37,202,169],{"class":43},[37,204,205],{"class":172}," 'cancel'",[37,207,157],{"class":58},[37,209,211,214,216],{"class":39,"line":210},12,[37,212,213],{"class":58},"    cancelTarget.value ",[37,215,184],{"class":43},[37,217,187],{"class":58},[37,219,221],{"class":39,"line":220},13,[37,222,193],{"class":58},[37,224,226,228,230,232,235],{"class":39,"line":225},14,[37,227,163],{"class":43},[37,229,166],{"class":58},[37,231,169],{"class":43},[37,233,234],{"class":172}," 'ship'",[37,236,157],{"class":58},[37,238,240,243,245],{"class":39,"line":239},15,[37,241,242],{"class":58},"    shipTarget.value ",[37,244,184],{"class":43},[37,246,187],{"class":58},[37,248,250],{"class":39,"line":249},16,[37,251,193],{"class":58},[37,253,255,257,259,261,264],{"class":39,"line":254},17,[37,256,163],{"class":43},[37,258,166],{"class":58},[37,260,169],{"class":43},[37,262,263],{"class":172}," 'change_address'",[37,265,157],{"class":58},[37,267,269,272,274],{"class":39,"line":268},18,[37,270,271],{"class":58},"    addressTarget.value ",[37,273,184],{"class":43},[37,275,187],{"class":58},[37,277,279],{"class":39,"line":278},19,[37,280,193],{"class":58},[37,282,284],{"class":39,"line":283},20,[37,285,286],{"class":125},"  \u002F\u002F … jeszcze cztery takie bloki\n",[37,288,290,292,295,298,301,303,306,309,311],{"class":39,"line":289},21,[37,291,163],{"class":43},[37,293,294],{"class":58}," (",[37,296,297],{"class":43},"typeof",[37,299,300],{"class":58}," close ",[37,302,169],{"class":43},[37,304,305],{"class":172}," 'function'",[37,307,308],{"class":58},") ",[37,310,154],{"class":54},[37,312,313],{"class":58},"()\n",[37,315,317],{"class":39,"line":316},22,[37,318,319],{"class":58},"}\n",[11,321,322],{},"Wszystkie bloki robią to samo. Zmienia się tylko jedna rzecz: która zmienna dostaje zamówienie.",[20,324,326],{"id":325},"mapa-zamiast-warunków","Mapa zamiast warunków",[11,328,329],{},"Skoro różni je tylko nazwa akcji i zmienna, wystarczy zapisać to połączenie w obiekcie:",[28,331,333],{"className":30,"code":332,"language":32,"meta":33,"style":33},"const actionTargets = {\n  refund: refundTarget,\n  cancel: cancelTarget,\n  ship: shipTarget,\n  change_address: addressTarget,\n  \u002F\u002F …\n}\n\nfunction handleAction(action, close) {\n  const target = actionTargets[action.key]\n  if (target) target.value = props.order\n  close?.()\n}\n",[15,334,335,347,352,357,362,367,372,376,380,396,409,420,428],{"__ignoreMap":33},[37,336,337,339,342,344],{"class":39,"line":40},[37,338,44],{"class":43},[37,340,341],{"class":47}," actionTargets",[37,343,51],{"class":43},[37,345,346],{"class":58}," {\n",[37,348,349],{"class":39,"line":68},[37,350,351],{"class":58},"  refund: refundTarget,\n",[37,353,354],{"class":39,"line":86},[37,355,356],{"class":58},"  cancel: cancelTarget,\n",[37,358,359],{"class":39,"line":104},[37,360,361],{"class":58},"  ship: shipTarget,\n",[37,363,364],{"class":39,"line":122},[37,365,366],{"class":58},"  change_address: addressTarget,\n",[37,368,369],{"class":39,"line":129},[37,370,371],{"class":125},"  \u002F\u002F …\n",[37,373,374],{"class":39,"line":136},[37,375,319],{"class":58},[37,377,378],{"class":39,"line":160},[37,379,133],{"emptyLinePlaceholder":132},[37,381,382,384,386,388,390,392,394],{"class":39,"line":178},[37,383,139],{"class":43},[37,385,142],{"class":54},[37,387,59],{"class":58},[37,389,148],{"class":147},[37,391,151],{"class":58},[37,393,154],{"class":147},[37,395,157],{"class":58},[37,397,398,401,404,406],{"class":39,"line":190},[37,399,400],{"class":43},"  const",[37,402,403],{"class":47}," target",[37,405,51],{"class":43},[37,407,408],{"class":58}," actionTargets[action.key]\n",[37,410,411,413,416,418],{"class":39,"line":196},[37,412,163],{"class":43},[37,414,415],{"class":58}," (target) target.value ",[37,417,184],{"class":43},[37,419,187],{"class":58},[37,421,422,425],{"class":39,"line":210},[37,423,424],{"class":54},"  close",[37,426,427],{"class":58},"?.()\n",[37,429,430],{"class":39,"line":220},[37,431,319],{"class":58},[11,433,434,435,437,438,441,442,445],{},"Działa to dokładnie tak samo. W pierwszej wersji każdy ",[15,436,17],{}," był sprawdzany osobno, ale klucze się nie powtarzają, więc i tak pasował najwyżej jeden. Nieznana akcja dalej niczego nie zmienia. ",[15,439,440],{},"close?.()"," wywoła funkcję tylko wtedy, gdy ją dostaniemy – tak jak ",[15,443,444],{},"typeof close === 'function'",".",[11,447,448],{},"Największy zysk widać przy zmianach. Nowa akcja to jedna linijka w obiekcie, a nie kolejny skopiowany blok, w którym łatwo zostawić starą nazwę zmiennej.",[20,450,452],{"id":451},"krok-dalej-jeden-stan","Krok dalej: jeden stan",[11,454,455],{},"Patrząc na ten kod dłużej, zauważyłem, że prawdziwy problem to nie same warunki, tylko osiem osobnych zmiennych. Teoretycznie kilka z nich może mieć wartość naraz, czyli kilka okien może być otwartych jednocześnie. A przecież w danej chwili otwarte jest jedno okno, dla jednego zamówienia.",[11,457,458],{},"Można to zapisać w jednej zmiennej:",[28,460,462],{"className":30,"code":461,"language":32,"meta":33,"style":33},"const activeAction = ref(null) \u002F\u002F { key, order } albo null\n\nfunction handleAction(action, close) {\n  activeAction.value = { key: action.key, order: props.order }\n  close?.()\n}\n",[15,463,464,484,488,504,514,520],{"__ignoreMap":33},[37,465,466,468,471,473,475,477,479,481],{"class":39,"line":40},[37,467,44],{"class":43},[37,469,470],{"class":47}," activeAction",[37,472,51],{"class":43},[37,474,55],{"class":54},[37,476,59],{"class":58},[37,478,62],{"class":47},[37,480,308],{"class":58},[37,482,483],{"class":125},"\u002F\u002F { key, order } albo null\n",[37,485,486],{"class":39,"line":68},[37,487,133],{"emptyLinePlaceholder":132},[37,489,490,492,494,496,498,500,502],{"class":39,"line":86},[37,491,139],{"class":43},[37,493,142],{"class":54},[37,495,59],{"class":58},[37,497,148],{"class":147},[37,499,151],{"class":58},[37,501,154],{"class":147},[37,503,157],{"class":58},[37,505,506,509,511],{"class":39,"line":104},[37,507,508],{"class":58},"  activeAction.value ",[37,510,184],{"class":43},[37,512,513],{"class":58}," { key: action.key, order: props.order }\n",[37,515,516,518],{"class":39,"line":122},[37,517,424],{"class":54},[37,519,427],{"class":58},[37,521,522],{"class":39,"line":129},[37,523,319],{"class":58},[28,525,529],{"className":526,"code":527,"language":528,"meta":33,"style":33},"language-vue shiki shiki-themes github-light github-dark","\u003CRefundDialog\n  v-if=\"activeAction?.key === 'refund'\"\n  :order=\"activeAction.order\"\n  @close=\"activeAction = null\"\n\u002F>\n","vue",[15,530,531,540,558,576,597],{"__ignoreMap":33},[37,532,533,536],{"class":39,"line":40},[37,534,535],{"class":58},"\u003C",[37,537,539],{"class":538},"s9eBZ","RefundDialog\n",[37,541,542,545,547,550,553,555],{"class":39,"line":68},[37,543,544],{"class":43},"  v-if",[37,546,184],{"class":58},[37,548,549],{"class":172},"\"",[37,551,552],{"class":58},"activeAction?.key ",[37,554,169],{"class":43},[37,556,557],{"class":172}," 'refund'\"\n",[37,559,560,563,566,568,570,573],{"class":39,"line":86},[37,561,562],{"class":58},"  :",[37,564,565],{"class":54},"order",[37,567,184],{"class":58},[37,569,549],{"class":172},[37,571,572],{"class":58},"activeAction.order",[37,574,575],{"class":172},"\"\n",[37,577,578,581,583,585,587,590,592,595],{"class":39,"line":104},[37,579,580],{"class":58},"  @",[37,582,154],{"class":54},[37,584,184],{"class":58},[37,586,549],{"class":172},[37,588,589],{"class":58},"activeAction ",[37,591,184],{"class":43},[37,593,594],{"class":47}," null",[37,596,575],{"class":172},[37,598,599],{"class":39,"line":122},[37,600,601],{"class":58},"\u002F>\n",[11,603,604,605,608],{},"Teraz nie ma już czego mapować. Zamknięcie dowolnego okna to ",[15,606,607],{},"activeAction = null",", a dwa okna naraz po prostu nie mogą się pojawić. To jednak większa zmiana, bo dotyka szablonu i wszystkich okien – w review zaproponowałem tylko mapę.",[20,610,612],{"id":611},"kiedy-zostać-przy-if","Kiedy zostać przy if",[11,614,615],{},"Mapa nie jest odpowiedzią na każdy zestaw warunków. Nie przerabiałbym kodu, gdy:",[617,618,619,626,636],"ul",{},[620,621,622,623,625],"li",{},"przypadki są dwa albo trzy – zwykły ",[15,624,17],{}," czyta się wtedy szybciej niż obiekt i funkcja,",[620,627,628,629,631,632,635],{},"każda gałąź robi coś innego (inne argumenty, zapytanie do API, inne okno) – wtedy ",[15,630,17],{}," albo ",[15,633,634],{},"switch"," pokazuje to wprost,",[620,637,638],{},"warunki nie są prostym porównaniem, np. zakresy liczb albo kilka pól naraz.",[11,640,641,642,631,646,649],{},"Mapa dobrze sprawdza się w jednym przypadku: gdy wiele gałęzi robi to samo, a różni je tylko to, ",[643,644,645],"em",{},"gdzie",[643,647,648],{},"czego"," używają.",[20,651,653],{"id":652},"jak-to-zaproponować","Jak to zaproponować",[11,655,656,657,659,660,663],{},"W komentarzu nie napisałem „przerób to”. Zapytałem, czy autor nie chciał tego zmapować, wkleiłem gotową wersję i zostawiłem wybór – mógł też zostać przy ",[15,658,17],{},"\u002F",[15,661,662],{},"else",". Kod był poprawny, więc to była sugestia, a nie błąd do naprawy. Gotowy kod w komentarzu oszczędza drugiej osobie czasu, a pytanie zamiast polecenia zostawia miejsce na powód, którego mogę nie znać.",[665,666,667],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":33,"searchDepth":68,"depth":68,"links":669},[670,671,672,673,674],{"id":22,"depth":68,"text":23},{"id":325,"depth":68,"text":326},{"id":451,"depth":68,"text":452},{"id":611,"depth":68,"text":612},{"id":652,"depth":68,"text":653},"2026-05-28","Jak zamienić długą listę warunków „jeśli akcja to X, otwórz okno X” na prosty obiekt w Vue 3 – i kiedy lepiej zostać przy zwykłym if.",false,"md",null,"post",{},"\u002Fog\u002Fblog\u002Fosiem-ifow-pl.jpg","\u002Fpl\u002Fblog\u002F2026\u002Fosiem-ifow-i-jedna-mapa",{"title":5,"description":676},"pl\u002Fblog\u002F2026\u002Fosiem-ifow-i-jedna-mapa",[528,687,688],"javascript","code-review","YUybCvTsGGuLlYSu4AxhnI67_a6yyI1hJeoLaTAh1ww",1792087426361]