[{"data":1,"prerenderedAt":1360},["ShallowReactive",2],{"$fwSPYkZpCTzP7pRy7-Vn1KMRwvaAlPE0QsOwFQLDpPHU":3,"$fMMUdSFktwQFqMVGPrTtt3EC5yheBp7PzwIqznamFcMo":134,"$f1Prj1xEczHja_-L7FyIGgRHd5_cSWHo7r6AE5aheAik":137,"$fc0LoAJgqXDLbKKd2JS_NpM4SuzBK8EycUXINSg09CKU":463,"$fM3ea55k6lKMPOTM84llDB26VSQDVVbxiQuSBFQw9P_c":466,"$fI5fDmvm-5tr9wcH0eHaKZa1j3y_FQIQaHHPqbZxAHJE":710,"mdc-9kgm6e-key":730,"mdc--239g37-key":742,"mdc--qj3qal-key":750,"mdc--2equ3a-key":758,"mdc-60vsts-key":766,"mdc--9zhfg-key":774,"mdc-sdegq6-key":842,"mdc-9ztts4-key":870,"mdc-21us8g-key":885,"mdc--1xp4vj-key":929,"mdc--s9ase5-key":951,"mdc--h45c6v-key":960,"mdc--mxc9cx-key":969,"mdc--h50r8k-key":977,"mdc-yqff2y-key":985,"mdc-ymuwrq-key":993,"mdc-dnej5w-key":1046,"mdc--agznh3-key":1097,"mdc-siqq7s-key":1154,"mdc--5ryinq-key":1187,"mdc--6brw36-key":1346},{"content":4,"quizQuestionContent":104,"type":123,"pageMeta":124},[5,9,13,16,20,23,27,31,34,38,41,45,48,52,55,59,63,66,70,73,77,80,84,87,91,94,98,101],{"id":6,"value":7,"isTypeH1":8},"1943","Централизованное состояние: React vs Redux/Effector",true,{"id":10,"value":11,"anchor":12,"isTypeH2":8},"4494","Теория: что мешает без менеджера","theory-what-prevents-without-a-manager",{"id":14,"value":15,"isTypeParagraph":8},"10344","Централизованное состояние на механизмах React обычно строится из `useState`/`useReducer` + `Context`. Такой подход работает, но упирается в две практические границы: (1) стоимость ререндеров и «ширина» обновлений, (2) сложность организации логики (асинхронность, кэширование, конкурентные обновления, согласованность данных между экранами).\n\nКонтекст — это механизм доставки значения «глубоко вниз», но не полноценный механизм «селективных подписок». При изменении значения контекста типичный эффект — обновления всех компонентов, которые читают этот контекст.  \nЭто означает, что «одно большое глобальное значение» в контексте часто превращается в «перерисовку всех потребителей при любом изменении любой части объекта».\n",{"id":17,"value":18,"anchor":19,"isTypeH3":8},"4524","Мини-схема проблемы контекста","mini-diagram-of-context-problem",{"id":21,"value":22,"isTypeParagraph":8},"10345","Если хранится единый объект:\n- `GlobalProvider value={{ user, settings, cart, ... }}`\n- изменился `cart`\n- обновились все потребители `user/settings/cart/...`, потому что поменялась ссылка на объект `value` (или его часть была пересобрана)\n\n```\nUI components\n   |\n   v  useContext(GlobalStateContext)\n[consumer A: user]   [consumer B: cart]   [consumer C: settings]\n        \\                 |                 /\n         \\                |                /\n          +---- Provider value changed ----+\n```",{"id":24,"value":25,"anchor":26,"isTypeH2":8},"4495","Что дают менеджеры состояния","what-state-managers-add",{"id":28,"value":29,"anchor":30,"isTypeH3":8},"4525","Точечные подписки (селекторы)","fine-grained-subscriptions-selectors",{"id":32,"value":33,"isTypeParagraph":8},"10346","В Redux-подходе (через React-Redux hooks) типовая схема заключается в том, что компонент подписывается не на весь store целиком, а на результат селектора. Перерисовка происходит только когда результат селектора изменился.  \nИдея в том, что компонент «зависит» не от всего глобального объекта, а от маленького результата селектора (например, `state.auth.userId`), поэтому обновления становятся уже и дешевле.",{"id":35,"value":36,"anchor":37,"isTypeH3":8},"4526","Предсказуемость модели обновлений","predictable-update-model",{"id":39,"value":40,"isTypeParagraph":8},"10347","Менеджеры состояния обычно навязывают (или поощряют) явную модель изменений: «событие/экшен → обработчик → новое состояние». Это снижает количество «скрытых» связей между компонентами и помогает сопровождать код, когда логика разрастается (появляются кэш, optimistic updates, синхронизация вкладок, восстановление состояния и т.п.).\n",{"id":42,"value":43,"anchor":44,"isTypeH3":8},"4527","Асинхронные операции как стандартный паттерн","async-as-a-standard-pattern",{"id":46,"value":47,"isTypeParagraph":8},"10348","При использовании только React часто получается «асинхронность размазана по компонентам» (эффекты в разных местах, ручная синхронизация загрузок, гонки запросов). Менеджеры состояния обычно предлагают стандартизированные способы: middleware/эффекты/события, централизованное место для побочных эффектов и единый подход к обработке ошибок и отмен.\n",{"id":49,"value":50,"anchor":51,"isTypeH3":8},"4528","Инструменты отладки и дисциплина","debugging-and-discipline",{"id":53,"value":54,"isTypeParagraph":8},"10349","На практике сильный выигрыш даёт не «красивость», а наблюдаемость: понятные причины изменения состояния, воспроизводимость, удобство анализа цепочки событий. Для командной разработки это часто превращается в снижение стоимости изменений и ревью.",{"id":56,"description":57,"titleAlert":58,"isTypeAlertWarning":8},"740","Контекст (как транспорт) и глобальное состояние (как архитектура) легко перепутать. Большой «global context» без селекции и без дисциплины обновлений часто приводит к трудно диагностируемым перерендерам и росту связности.",null,{"id":60,"value":61,"anchor":62,"isTypeH2":8},"4496","Как сделать централизованное состояние на React","centralized-state-with-react-only",{"id":64,"value":65,"isTypeParagraph":8},"10350","Ниже приведён рабочий «чисто React» подход (Context + useReducer) и показано, где начинаются ограничения.",{"id":67,"value":68,"anchor":69,"isTypeH3":8},"4529","Базовый вариант: один контекст (часто проблемный)","basic-single-context-often-problematic",{"id":71,"value":72,"isTypeParagraph":8},"10351","```\nimport React, { createContext, useContext, useMemo, useReducer } from \"react\";\n\nconst AppStateContext = createContext(null);\n\nconst initialState = {\n  user: null,\n  cart: [],\n  settings: { theme: \"light\" },\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case \"user/set\":\n      return { ...state, user: action.payload };\n    case \"cart/add\":\n      return { ...state, cart: [...state.cart, action.payload] };\n    case \"settings/theme\":\n      return { ...state, settings: { ...state.settings, theme: action.payload } };\n    default:\n      return state;\n  }\n}\n\nexport function AppStateProvider({ children }) {\n  const [state, dispatch] = useReducer(reducer, initialState);\n\n  // Без useMemo объект будет новым на каждый render Provider,\n  // а потребители будут обновляться чаще, чем нужно.\n  const value = useMemo(() => ({ state, dispatch }), [state]);\n\n  return (\n    \u003CAppStateContext.Provider value={value}>\n      {children}\n    \u003C/AppStateContext.Provider>\n  );\n}\n\nexport function useAppState() {\n  const ctx = useContext(AppStateContext);\n  if (!ctx) throw new Error(\"Provider is missing\");\n  return ctx;\n}\n```\n\nПроблема данного подхода в том, что `state` — один объект, и любое изменение в нём означает новое значение `value` провайдера, а значит — обновления всех потребителей контекста, читающих этот контекст.  \nДаже если изменения касаются только `cart`, компонент, читающий `user`, всё равно может обновляться, потому что обновилось общее значение, которое передаётся через контекст.",{"id":74,"value":75,"anchor":76,"isTypeH3":8},"4530","Улучшение: разделение контекстов (сужение обновлений)","splitting-contexts-to-narrow-updates",{"id":78,"value":79,"isTypeParagraph":8},"10352","Разделение «данные» и «dispatch» уже помогает, потому что `dispatch` обычно стабилен.\n\n```\nimport React, { createContext, useContext, useMemo, useReducer } from \"react\";\n\nconst StateContext = createContext(null);\nconst DispatchContext = createContext(null);\n\nfunction reducer(state, action) { /* тот же reducer */ }\n\nexport function Provider({ children }) {\n  const [state, dispatch] = useReducer(reducer, initialState);\n\n  // Состояние меняется — потребители StateContext обновятся.\n  // Dispatch стабилен — потребители DispatchContext обычно не обновятся.\n  const memoState = useMemo(() => state, [state]);\n\n  return (\n    \u003CDispatchContext.Provider value={dispatch}>\n      \u003CStateContext.Provider value={memoState}>\n        {children}\n      \u003C/StateContext.Provider>\n    \u003C/DispatchContext.Provider>\n  );\n}\n\nexport const useAppDispatch = () => useContext(DispatchContext);\nexport const useAppState = () => useContext(StateContext);\n```\n\nНо даже здесь все потребители `StateContext` будут обновляться при любом изменении `state`, потому что контекст не знает, «какая часть состояния нужна компоненту».  \nИменно эту «селективность» обычно и дают менеджеры состояния через селекторы/подписки.",{"id":81,"value":82,"anchor":83,"isTypeH2":8},"4497","Пример: что именно даёт Redux (hooks)","example-what-redux-hooks-provide",{"id":85,"value":86,"isTypeParagraph":8},"10353","\nТиповой подход: компонент читает только нужный фрагмент состояния через селектор, а обновляется только при изменении результата этого селектора.  \nОтсюда следует важное правило: селектор должен возвращать стабильные значения (например, примитивы или мемоизированные объекты), иначе можно случайно создавать «ложные изменения».\n\n```\nimport React from \"react\";\nimport { useSelector, useDispatch } from \"react-redux\";\n\nexport function CartTotal() {\n  // Компонент зависит только от cart.total\n  const total = useSelector((state) => state.cart.total);\n  return \u003Cdiv>Total: {total}\u003C/div>;\n}\n\nexport function ThemeSwitch() {\n  // Компонент зависит только от settings.theme\n  const theme = useSelector((state) => state.settings.theme);\n  const dispatch = useDispatch();\n\n  return (\n    \u003Cbutton\n      onClick={() =>\n        dispatch({\n          type: \"settings/theme\",\n          payload: theme === \"light\" ? \"dark\" : \"light\",\n        })\n      }\n    >\n      Theme: {theme}\n    \u003C/button>\n  );\n}\n```\n\nЕсли меняется `settings.theme`, то `CartTotal` обычно не должен перерисовываться, потому что его зависимость (`state.cart.total`) не изменилась.  \nДля контекста с единым объектом такое поведение «по умолчанию» недостижимо без дополнительных приёмов (разбиение на много контекстов, дополнительные селекторные обёртки, внешние хранилища и т.п.).",{"id":88,"value":89,"anchor":90,"isTypeH2":8},"4498","Пример: что даёт Effector (реактивные единицы)","example-what-effector-provides",{"id":92,"value":93,"isTypeParagraph":8},"10354","В effector состояние хранится в store-юнитах, которые обновляются, когда возвращается новое значение (обычно требуется иммутабельный стиль обновлений).  \nТакже поддерживаются производные store (derived), которые вычисляются из других store и обновляются автоматически при изменениях источников.\n\n```\nimport { createEvent, createStore, combine } from \"effector\";\n\nconst itemAdded = createEvent();\nconst themeChanged = createEvent();\n\nconst $cart = createStore([])\n  .on(itemAdded, (cart, item) => [...cart, item]);\n\nconst $theme = createStore(\"light\")\n  .on(themeChanged, (_, nextTheme) => nextTheme);\n\nconst $cartCount = $cart.map((cart) => cart.length);\n\n// Производное состояние (derived) собирается из других store\nconst $viewModel = combine({\n  theme: $theme,\n  cartCount: $cartCount,\n});\n```\n\nВажная практическая идея: состояние естественно дробится на небольшие store, поэтому изменение одной части не обязано затрагивать подписчиков другой части (это достигается структурой, а не только оптимизациями).  \nТакже становится проще выносить доменную логику из компонентов, уменьшая их связность с источниками данных.",{"id":95,"value":96,"anchor":97,"isTypeH2":8},"4499","Таблица: React-механизмы vs менеджеры","react-vs-state-managers-table",{"id":99,"value":100,"isTypeParagraph":8},"10355","| Подход | Где хранится состояние | Как распространяются обновления | Типичные риски |\n|---|---|---|---|\n| `useState`/`useReducer` локально | В компоненте | По дереву рендера от родителя | Дублирование состояния между ветками, сложная синхронизация |\n| `Context + useReducer` | В провайдере | Потребители контекста обновляются при изменении `value` | «Широкие» ререндеры, крупные контексты, пересоздание `value` |\n| Redux (React-Redux hooks) | В store | Обновление по результату селектора | Ошибки селекторов, возврат новых объектов без мемоизации |\n| Effector | В store-юнитах | Реактивные связи, derived store | Сложность освоения модели событий/юнитов на старте |",{"id":102,"value":103,"isTypeParagraph":8},"10356","Итого: контекст и локальный стейт позволяют централизовать состояние, но по умолчанию не дают селективных подписок и масштабируемых паттернов, из‑за чего растут перерисовки и сложность сопровождения.  \nRedux/Effector обычно добавляют более управляемую модель обновлений, точечные реакции на изменения и зрелые практики, а селекторы (или реактивные derived-единицы) помогают обновлять только те части интерфейса, которым действительно нужно обновление.",{"id":105,"options":106,"hint":120,"solution":121,"description":122},"1172",[107,111,114,117],{"id":108,"label":109,"isCorrect":110},"4832","Основная проблема встроенных механизмов React - отсутствие возможности хранить состояние вообще, поэтому библиотеки необходимы для любого нетривиального приложения. (Неверно: React позволяет хранить состояние через useState и useReducer)",false,{"id":112,"label":113,"isCorrect":110},"4833","Redux и подобные библиотеки нужны исключительно для красивого кода и не решают реальных проблем производительности, так как React Context полностью оптимизирован в последних версиях. (Неверно: Context по-прежнему вызывает ререндер всех потребителей при любом изменении значения)",{"id":115,"label":116,"isCorrect":8},"4834","Специализированные библиотеки управления состоянием (Redux, Effector) решают фундаментальные проблемы масштабирования приложений: обеспечивают предсказуемость обновлений через однонаправленный поток данных, оптимизируют производительность через точечные подписки на изменения, предоставляют стандартизированные паттерны для асинхронных операций и мощные инструменты для отладки, что критично для крупных проектов с командной разработкой.",{"id":118,"label":119,"isCorrect":110},"4835","Главное преимущество специализированных библиотек - возможность использовать их без React, так как встроенные механизмы привязывают состояние к компонентам. (Неверно: хотя некоторые библиотеки действительно framework-agnostic, их основная ценность не в этом)","При выборе между «React-only» и менеджером состояния удобно проверять три вопроса:\n1) Сколько независимых частей состояния должно жить «вне» конкретного компонента?  \n2) Насколько важно, чтобы обновления были селективными (подписка на малый фрагмент)?  \n3) Нужны ли стандартные паттерны для асинхронности и развитая отладка?","**Правильный ответ: 3** - Специализированные библиотеки управления состоянием (Redux, Effector) решают фундаментальные проблемы масштабирования приложений: обеспечивают предсказуемость обновлений через однонаправленный поток данных, оптимизируют производительность через точечные подписки на изменения, предоставляют стандартизированные паттерны для асинхронных операций и мощные инструменты для отладки, что критично для крупных проектов с командной разработкой.","Что мешает организовать централизованное состояние без менеджера состояния?. Если организовать состояние механизмами реакта: контекстом, стейтом, в чем проблема? Что менеджеры состояния привносят?","quizQuestion",{"title":125,"description":126,"ogTitle":7,"ogDescription":126,"ogImageUrl":127,"canonical":58,"ogLocale":128,"ogSiteName":129,"ogImageType":130,"ogImageWidth":131,"ogImageHeight":132,"ogType":133,"ogUrl":58},"Трудности управления централизованным состоянием в React","Почему Context+State не всегда достаточно и что дают менеджеры состояния: подписки, предсказуемость, async-паттерны, отладка.","/og-image.png","ru_RU","goodwebjob.ru","image_jpeg","1200","630","article",{"siteName":135,"siteUrl":136},"GOOD WEB JOB!","https://goodwebjob.ru",{"slugs":138},[139,142,145,148,151,154,157,160,163,166,169,172,175,178,181,184,187,190,193,196,199,202,205,208,211,214,217,220,223,226,229,232,235,238,241,244,247,250,253,256,259,262,265,268,271,274,277,280,283,286,289,292,295,298,301,304,307,310,313,316,319,322,325,328,331,334,337,340,343,346,349,352,355,358,361,364,367,370,373,376,379,382,385,388,391,394,397,400,403,406,409,412,415,418,421,424,427,430,433,436,439,442,445,448,451,454,457,460],{"name":140,"value":141},"Теоретические задания","theoretical-tasks",{"name":143,"value":144},"Что вернёт этот код: typeof (function(){})()","what-this-code-will-return-typeof-function",{"name":146,"value":147},"С чего начать?","where-to-begin",{"name":149,"value":150},"Почему опасно писать прямо в прототипы базовых типов?","why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":152,"value":153},"Backend","backend",{"name":155,"value":156},"Frontend","frontend",{"name":158,"value":159},"Какие логические значения в console.log будут получены?","prototype-what-logical-values-will-be-received-in-console-log",{"name":161,"value":162},"Нечётные числа должны отсортироваться по возрастанию, а чётные должны остаться на своих местах","odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":164,"value":165}," Найти в массиве неповторяющиеся числа","find-non-repeating-numbers-in-an-array",{"name":167,"value":168},"arr.push(0) повлияет на массив так же, как если бы мы выполнили...","arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":170,"value":171},"Дана строка: 'one.two.three.four.five'. Необходимо из строки сделать вложенный объект","the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":173,"value":174},"Реализовать функцию, похоже как в Jquery","implement-a-function-similar-to-jquery",{"name":176,"value":177},"Для каждого вложенного объекта нужно добавить свойство level, которое равняется числу - номер вложенности","for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":179,"value":180},"Какое значение выведет консоль с object.property?","what-value-will-the-console-output-with-object-property",{"name":182,"value":183},"Что выведется в console.log([arr[0](), arr[0]()])?","what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":185,"value":186},"Вернуть массив от 1 до n, где числа, кратные 3, заменены на 'fizz', кратные 5 - на 'buzz', а кратные и 3, и 5 одновременно - на 'fizzbuzz'","returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":188,"value":189},"Необходимо проверить, являются ли две строки анаграммами друг друга","checks-whether-two-strings-are-anagrams-of-each-other",{"name":191,"value":192},"Определить, является ли слово палиндромом","determines-whether-a-word-is-a-palindrome",{"name":194,"value":195},"Есть массив, в котором лежат объекты с датами, необходимо отсортировать даты по возрастанию","there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":197,"value":198},"Реализовать функцию, принимающую аргументы \"*\", \"1\", \"b\", \"1c\" и возвращающую строку \"1*b*1c\"","implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":200,"value":201},"Дано дерево (вложенный объект), надо найти сумму всех вершин","given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":203,"value":204},"Для каждой ветви дерева записать номер вложенности данной ветви","for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":206,"value":207},"Есть слова в массиве, необходимо определить, состоят ли они из одних и тех же букв","there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":209,"value":210},"Числа от 1 до 100 находятся в массиве, они хаотично перемешанные, но в нём не хватает одного числа из этой последовательности. Необходимо найти его","the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"name":212,"value":213},"Есть строка, состоящая из разных скобок, необходимо проверить, закрыты ли все","there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":215,"value":216},"Напишите функцию, который сделает из массива объект","write-a-function-that-will-make-an-object-out-of-an-array",{"name":218,"value":219},"Что выведет console.log в результате выполнения цикла while?","what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":221,"value":222},"Есть функция и объект. Напишите все известные вам способы, чтобы вывести в консоли значение x из объекта, используя функцию","there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":224,"value":225},"Что выведет консоль в случае присвоения свойства массиву по строковому отрицательному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":227,"value":228},"Что выведет консоль в случае удаления элемента массива с помощью оператора delete?","what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":230,"value":231},"Уникализация значений в массиве","unifying-values-in-an-array",{"name":233,"value":234},"«Расплющивание» массива","flattening-the-array",{"name":236,"value":237},"Что вернёт метод book.getUpperName()?","what-will-the-book-get-upper-name-method-return",{"name":239,"value":240},"Сжатие строк","string-compression",{"name":242,"value":243},"Что выведет консоль в случае присвоения свойства массиву по строковому положительному индексу?","what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":245,"value":246},"Что получится в результате передачи объекта как аргумента в функцию и выполнения кода?","what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":248,"value":249},"Как браузер после ввода домена понимает, откуда брать сайт?","how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":251,"value":252},"Как домен попадает в DNS в таблицу соответствия: домен – ip","how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":254,"value":255},"Как браузер решает, какое соединение ему открывать, TCP или UDP?","how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":257,"value":258},"Ключевые отличия TCP и UDP","key-differences-between-tcp-and-udp",{"name":260,"value":261},"\"TCP/IP\" - кем является TCP, а кем IP в данном случае?","tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":263,"value":264},"Что такое HTTP и из чего состоит?","what-is-http-and-what-does-it-consist-of",{"name":266,"value":267},"Что такое заголовки в HTTP и зачем они нужны?","what-are-http-headers-and-why-do-we-need-them",{"name":269,"value":270},"Что такое параметры в HTTP?","what-are-http-parameters",{"name":272,"value":273},"Где находится HTML-код в структуре HTTP-ответа?","where-is-the-html-code-located-in-the-http-response-structure",{"name":275,"value":276},"Что такое HTML?","what-is-html",{"name":278,"value":279},"Чем отличаются 1.0, 1.1, 2.0, 3.0 версии HTTP?","what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":281,"value":282},"Пользователь авторизован на сайте. Как сервер узнает об этом с последующими другими заходами, что «я – авторизованный пользователь»?","the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":284,"value":285},"Что такое cookie?","what-is-a-cookie",{"name":287,"value":288},"Кто является инициатором записи cookie в браузере?","who-initiates-the-cookie-recording-in-the-browser",{"name":290,"value":291},"Есть ли возможность с клиента (с браузера) управлять cookie?","is-it-possible-to-manage-cookies-from-the-client-browser",{"name":293,"value":294},"Лайвкодинг","livecoding",{"name":296,"value":297},"Что вернёт следующий код? Object.create(null).hasOwnProperty('toString')","what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":299,"value":300},"Всё, что идет по HTTPS – оно защищено?","is-everything-that-goes-through-https-secure",{"name":302,"value":303},"Все данные зашифрованы, используется https. Хакер взламывает dns и делает подмену одного ip на другой, на фишинговый сайт. В этом случае, злоумышленник может получить данные (логин \\ пароль)?","all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":305,"value":306},"Есть веб-приложение. Помимо HTTP, какие протоколы того же уровня (Application Layer) можно дополнительно использовать в веб-приложении в браузере?","there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":308,"value":309},"Как браузер парсит JavaScript и изображения при рендеринге?","how-the-browser-parses-javascript-and-images-when-rendering",{"name":311,"value":312},"Что происходит, когда HTTP прислал HTML? Что браузер дальше делает c HTML с учетом того, что она валидная?","what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":314,"value":315},"Что в браузере блокирует рендеринг страницы?","what-is-blocking-the-page-rendering-in-the-browser",{"name":317,"value":318},"Что такое DOM в браузере? Что такое CSSOM?","what-is-dom-in-a-browser-what-is-cssom",{"name":320,"value":321},"Что является узлами в DOM?","what-are-nodes-in-the-dom",{"name":323,"value":324},"Из чего состоит CSSOM?","what-does-cssom-consist-of",{"name":326,"value":327},"Дан HTML-код. Какой будет цвет у текста «Some dummy text»?","the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":329,"value":330},"Есть шаблон HTML и CSS кода. Какой будет цвет у текста «Таким образом, постоянное»?","there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":332,"value":333},"Есть шаблон вложенного HTML кода. Какой будет цвет у текста «One more dummy text»?","there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":335,"value":336},"Есть шаблон вложенного HTML кода. Будет ли display:block у body влиять на span?","there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":338,"value":339},"Есть HTML код. Будет ли font-weight на span влиять?","there-is-an-html-code-will-font-weight-affect-span",{"name":341,"value":342},"Flexbox и Grid, чем отличаются друг от друга?","what-are-the-differences-between-flexbox-and-grid",{"name":344,"value":345},"Заменяют ли Flexbox и Grid друг друга?","do-flexbox-and-grid-replace-each-other",{"name":347,"value":348},"Есть CSS и JS анимация. Какая между ними разница, что быстрее, что более удобно?","there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"name":350,"value":351},"Сборник задач","tasks",{"name":353,"value":354},"Какие способы объявления функции есть в JavaScript?","what-are-the-ways-to-declare-a-function-in-javascript",{"name":356,"value":357},"Что такое this в JavaScript?","what-is-this-in-javascript",{"name":359,"value":360},"Что такое Event Loop, как работает?","what-is-an-event-loop-and-how-does-it-work",{"name":362,"value":363},"Что будет, если вызвать typeof на необъявленной переменной?","what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":365,"value":366},"Что показывает оператор typeof в JavaScript?","what-does-the-typeof-operator-show-in-javascript",{"name":368,"value":369},"Какие типы данных существует в JavaScript?","what-types-of-data-exist-in-javascript",{"name":371,"value":372},"Какую структуру использовать для хранения упорядоченного списка строк в JavaScript?","what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":374,"value":375},"Что вернет typeof для массива?","what-will-typeof-return-for-an-array",{"name":377,"value":378},"Почему оператор typeof, применённый к массиву, возвращает объект?","why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":380,"value":381},"Если нужно хранить список уникальных строк, какую структуру данных выбрать?","if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":383,"value":384},"Что возвращает typeof для new Set в JavaScript?","what-does-typeof-return-for-new-set-in-javascript",{"name":386,"value":387},"Для чего нужен React, какие он решает проблемы?","what-is-react-used-for-and-what-problems-does-it-solve",{"name":389,"value":390},"Если убрать в React VDOM/Fiber, и вручную изменять DOM, разве это не оптимально?","if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":392,"value":393},"Есть блок кода. Что в реальном DOM изменится после нажатия на кнопку?","there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":395,"value":396},"Есть код, в котором список и кнопка. Что в реальном DOM изменится после нажатия на кнопку?","there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":398,"value":399},"Зачем нужен Redux (Mobx/Effector)? Зачем нужен менеджер состояния? Какие проблемы решает?","why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":401,"value":402},"Как диагностировать и исправить нежелательное изменение цвета фона по клику на кнопку, если исходный код сайта запутан и недоступен для прямого чтения?","how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"name":404,"value":405},"Разрабатывал, взял закоммитил, запушил. Оказалось, что запушил не в ту ветку, точнее, коммит не в ту ветку. Какие действия?","developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":407,"value":408},"В git есть несколько вариантов слияния веток, какие? Чем отличаются?","git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":410,"value":411},"Какие существуют стратегии ветвления для работы команды? Что это такое?","what-are-the-branching-strategies-for-the-team-what-is-it",{"name":413,"value":414},"По каким характеристикам, ревьюер понимает, что данный код - хороший, а этот код - плохой?","how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"name":416,"value":417},"Дан фрагмент bash-скрипта: cd ~; mkdir foo... Что в нем происходит?","here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":419,"value":420},"Дан фрагмент bash-скрипта: target=$(ps -Af | grep $1 | head -n 1)...","here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"name":422,"value":423},"Что такое алгоритмическая сложность?","what-is-algorithmic-complexity",{"name":425,"value":426},"Какая алгоритмическая сложность у \"быстрой сортировки\"?","what-is-the-algorithmic-complexity-of-quick-sort",{"name":428,"value":429},"Почему в JavaScript два объекта с одинаковым содержимым при сравнении возвращают false?","why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":431,"value":432},"Каким способом может выполняться авторизация пользователя на сайте?","how-can-a-user-be-authorized-on-a-website",{"name":434,"value":435},"В чем разница между микро- и макро-тасками в JavaScript?","what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":437,"value":438},"В комнате три человека. Какова вероятность того, что хотя бы двое из них одного пола? То есть два и более.","there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":440,"value":441},"Есть монета. Ее подбрасывают пять раз подряд. Каждый раз записывается, что выпало - орел или решка. Сколько разных последовательностей орлов и решек может при этом получиться?","there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":443,"value":444},"Как гарантированно найти лёгкую фальшивую монету среди 8 за минимальное число взвешиваний на чашечных весах?","how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"name":446,"value":447},"Подготовка к тех.интервью","technical-interview",{"name":449,"value":450},"Верно ли утверждение, что злоумышленник, контролирующий роутер и прослушивающий трафик, может получить логины и пароли от сайтов, на которые заходит клиент?","is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":452,"value":453},"Что такое DNS, как DNS находит нужный IP-адрес?","what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":455,"value":456},"Переменные объявлены следующим образом: a=3; b=«hello»;. Укажите правильное утверждение","variables-are-declared-as-follows-specify-the-correct-statement",{"name":458,"value":459},"Какой механизм лежит в основе оптимизации обновлений DOM в React?","what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":461,"value":462},"Что мешает организовать централизованное состояние без менеджера состояния? Если организовать состояние механизмами реакта: контекстом, стейтом, в чем проблема? Что менеджеры состояния привносят?","what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",[464],{"label":446,"slug":447,"to":465},"/technical-interview/where-to-begin",{"navigationList":467,"navigationSublist":473},[468,470],{"path":465,"isActive":110,"name":146,"icon":469,"isNavbarMobileDisabled":8},"material-symbols:visibility-outline-rounded",{"path":471,"isActive":8,"name":350,"icon":472,"isNavbarMobileDisabled":110},"/technical-interview/tasks","material-symbols:task-outline",[474,481,500,509,514,609,626,633,638,681,696,701],{"title":475,"list":476,"isOpened":110},"Bash",[477,479],{"name":416,"path":478,"isActive":110},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-cd-mkdir-foo-what-is-happening-in-this-script",{"name":419,"path":480,"isActive":110},"/technical-interview/tasks/here-is-a-fragment-of-a-bash-script-target-ps-af-grep-1-head-n-1",{"title":482,"list":483,"isOpened":110},"CSS",[484,486,488,490,492,494,496,498],{"name":326,"path":485,"isActive":110},"/technical-interview/tasks/the-html-code-is-given-what-will-be-the-color-of-the-some-dummy-text",{"name":329,"path":487,"isActive":110},"/technical-interview/tasks/there-is-a-template-for-html-and-css-code-what-color-will-the-text-thus-constant-have",{"name":332,"path":489,"isActive":110},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-what-will-be-the-color-of-the-one-more-dummy-text",{"name":335,"path":491,"isActive":110},"/technical-interview/tasks/there-is-a-template-for-embedded-html-code-will-there-be-a-display-does-bodys-block-affect-span",{"name":338,"path":493,"isActive":110},"/technical-interview/tasks/there-is-an-html-code-will-font-weight-affect-span",{"name":341,"path":495,"isActive":110},"/technical-interview/tasks/what-are-the-differences-between-flexbox-and-grid",{"name":344,"path":497,"isActive":110},"/technical-interview/tasks/do-flexbox-and-grid-replace-each-other",{"name":347,"path":499,"isActive":110},"/technical-interview/tasks/there-are-css-and-js-animations-what-is-the-difference-between-them-and-which-is-faster-and-more-convenient",{"title":501,"list":502,"isOpened":110},"Git",[503,505,507],{"name":404,"path":504,"isActive":110},"/technical-interview/tasks/developed-it-committed-it-and-launched-it-it-turned-out-that-i-had-pushed-it-to-the-wrong-branch-or-rather-the-commit-was-in-the-wrong-branch-what-actions",{"name":407,"path":506,"isActive":110},"/technical-interview/tasks/git-has-several-options-for-merging-branches-which-ones-how-are-they-different",{"name":410,"path":508,"isActive":110},"/technical-interview/tasks/what-are-the-branching-strategies-for-the-team-what-is-it",{"title":510,"list":511,"isOpened":110},"HTML",[512],{"name":275,"path":513,"isActive":110},"/technical-interview/tasks/what-is-html",{"title":515,"list":516,"isOpened":110},"JavaScript",[517,519,521,523,525,527,529,531,533,535,537,539,541,543,545,547,549,551,553,555,557,559,561,563,565,567,569,571,573,575,577,579,581,583,585,587,589,591,593,595,597,599,601,603,605,607],{"name":158,"path":518,"isActive":110},"/technical-interview/tasks/prototype-what-logical-values-will-be-received-in-console-log",{"name":149,"path":520,"isActive":110},"/technical-interview/tasks/why-is-it-dangerous-to-write-directly-to-the-prototypes-of-basic-types",{"name":296,"path":522,"isActive":110},"/technical-interview/tasks/what-will-the-following-code-return-object-create-null-has-own-property-to-string",{"name":179,"path":524,"isActive":110},"/technical-interview/tasks/what-value-will-the-console-output-with-object-property",{"name":182,"path":526,"isActive":110},"/technical-interview/tasks/what-will-be-displayed-in-console-log-arr-0-arr-0",{"name":218,"path":528,"isActive":110},"/technical-interview/tasks/what-will-console-log-output-as-a-result-of-executing-the-while-loop",{"name":221,"path":530,"isActive":110},"/technical-interview/tasks/there-is-a-function-and-an-object-write-all-the-ways-you-know-to-output-the-value-of-x-from-an-object-in-the-console-using-the-function",{"name":236,"path":532,"isActive":110},"/technical-interview/tasks/what-will-the-book-get-upper-name-method-return",{"name":455,"path":534,"isActive":110},"/technical-interview/tasks/variables-are-declared-as-follows-specify-the-correct-statement",{"name":242,"path":536,"isActive":110},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-positive-string-index",{"name":224,"path":538,"isActive":110},"/technical-interview/tasks/what-will-the-console-display-if-a-property-is-assigned-to-an-array-using-a-negative-string-index",{"name":227,"path":540,"isActive":110},"/technical-interview/tasks/what-will-the-console-output-if-an-array-element-is-deleted-using-the-delete-operator",{"name":143,"path":542,"isActive":110},"/technical-interview/tasks/what-this-code-will-return-typeof-function",{"name":245,"path":544,"isActive":110},"/technical-interview/tasks/what-will-happen-when-an-object-is-passed-as-an-argument-to-a-function-and-the-code-is-executed",{"name":353,"path":546,"isActive":110},"/technical-interview/tasks/what-are-the-ways-to-declare-a-function-in-javascript",{"name":356,"path":548,"isActive":110},"/technical-interview/tasks/what-is-this-in-javascript",{"name":359,"path":550,"isActive":110},"/technical-interview/tasks/what-is-an-event-loop-and-how-does-it-work",{"name":362,"path":552,"isActive":110},"/technical-interview/tasks/what-happens-if-you-call-typeof-on-an-undeclared-variable",{"name":365,"path":554,"isActive":110},"/technical-interview/tasks/what-does-the-typeof-operator-show-in-javascript",{"name":368,"path":556,"isActive":110},"/technical-interview/tasks/what-types-of-data-exist-in-javascript",{"name":371,"path":558,"isActive":110},"/technical-interview/tasks/what-is-the-best-structure-to-use-for-storing-an-ordered-list-of-strings-in-javascript",{"name":374,"path":560,"isActive":110},"/technical-interview/tasks/what-will-typeof-return-for-an-array",{"name":377,"path":562,"isActive":110},"/technical-interview/tasks/why-does-the-typeof-operator-applied-to-an-array-return-an-object",{"name":380,"path":564,"isActive":110},"/technical-interview/tasks/if-you-need-to-store-a-list-of-unique-strings-which-data-structure-should-i-choose",{"name":383,"path":566,"isActive":110},"/technical-interview/tasks/what-does-typeof-return-for-new-set-in-javascript",{"name":428,"path":568,"isActive":110},"/technical-interview/tasks/why-do-two-objects-with-the-same-content-return-false-when-compared-in-javascript",{"name":434,"path":570,"isActive":110},"/technical-interview/tasks/what-is-the-difference-between-micro-and-macro-tasks-in-javascript",{"name":167,"path":572,"isActive":110},"/technical-interview/tasks/arr-push-0-will-affect-the-array-in-the-same-way-as-if-we-performed",{"name":185,"path":574,"isActive":110},"/technical-interview/tasks/returns-an-array-from-1-to-n-replacing-numbers-that-are-multiples-of-3-with-fizz-numbers-that-are-multiples-of-5-with-buzz-and-numbers-that-are-multiples-of-both-3-and-5-with-fizzbuzz",{"name":170,"path":576,"isActive":110},"/technical-interview/tasks/the-string-one-two-three-four-five-is-given-it-is-necessary-to-make-a-nested-object-out-of-the-string",{"name":200,"path":578,"isActive":110},"/technical-interview/tasks/given-a-tree-nested-object-it-is-necessary-to-find-the-sum-of-all-vertices",{"name":176,"path":580,"isActive":110},"/technical-interview/tasks/for-each-nested-object-you-need-to-add-the-level-property-which-is-equal-to-a-number-the-nesting-number",{"name":203,"path":582,"isActive":110},"/technical-interview/tasks/for-each-branch-of-the-tree-write-down-the-nesting-number-of-this-branch",{"name":194,"path":584,"isActive":110},"/technical-interview/tasks/there-is-an-array-containing-objects-with-dates-that-need-to-be-sorted-by-date",{"name":206,"path":586,"isActive":110},"/technical-interview/tasks/there-are-words-in-the-array-it-is-necessary-to-determine-whether-they-consist-of-the-same-letters",{"name":212,"path":588,"isActive":110},"/technical-interview/tasks/there-is-a-string-consisting-of-different-brackets-it-is-necessary-to-check-whether-all-are-closed",{"name":164,"path":590,"isActive":110},"/technical-interview/tasks/find-non-repeating-numbers-in-an-array",{"name":215,"path":592,"isActive":110},"/technical-interview/tasks/write-a-function-that-will-make-an-object-out-of-an-array",{"name":188,"path":594,"isActive":110},"/technical-interview/tasks/checks-whether-two-strings-are-anagrams-of-each-other",{"name":161,"path":596,"isActive":110},"/technical-interview/tasks/odd-numbers-should-be-sorted-in-ascending-order-and-even-numbers-should-remain-in-their-original-positions",{"name":191,"path":598,"isActive":110},"/technical-interview/tasks/determines-whether-a-word-is-a-palindrome",{"name":233,"path":600,"isActive":110},"/technical-interview/tasks/flattening-the-array",{"name":197,"path":602,"isActive":110},"/technical-interview/tasks/implement-a-function-that-accepts-arguments-1-b-1c-and-the-return-string-1-b-1c",{"name":239,"path":604,"isActive":110},"/technical-interview/tasks/string-compression",{"name":230,"path":606,"isActive":110},"/technical-interview/tasks/unifying-values-in-an-array",{"name":209,"path":608,"isActive":110},"/technical-interview/tasks/the-numbers-from-1-to-100-are-in-the-array-they-are-randomly-mixed-but-it-lacks-one-number-from-this-sequence-it-is-necessary-to-find-him",{"title":610,"list":611,"isOpened":110},"React",[612,614,616,618,620,622,624],{"name":386,"path":613,"isActive":110},"/technical-interview/tasks/what-is-react-used-for-and-what-problems-does-it-solve",{"name":458,"path":615,"isActive":110},"/technical-interview/tasks/what-is-the-underlying-mechanism-for-optimizing-dom-updates-in-react",{"name":389,"path":617,"isActive":110},"/technical-interview/tasks/if-you-remove-the-vdom-fiber-in-react-and-manually-change-the-dom-isn-t-that-optimal",{"name":392,"path":619,"isActive":110},"/technical-interview/tasks/there-is-a-block-of-code-what-changes-in-the-real-dom-after-clicking-the-button",{"name":395,"path":621,"isActive":110},"/technical-interview/tasks/there-is-a-code-in-which-there-is-a-list-and-a-button-what-will-change-in-the-real-dom-after-clicking-on-the-button",{"name":398,"path":623,"isActive":110},"/technical-interview/tasks/why-do-we-need-redux-mobx-effector-why-do-we-need-a-state-manager-what-problems-does-it-solve",{"name":461,"path":625,"isActive":110},"/technical-interview/tasks/what-prevents-you-from-organizing-a-centralized-state-without-a-state-manager-if-you-organize-the-state-using-react-context-and-state-mechanisms-what-is-the-problem-what-do-state-managers-add",{"title":627,"list":628,"isOpened":110},"Алгоритмы",[629,631],{"name":422,"path":630,"isActive":110},"/technical-interview/tasks/what-is-algorithmic-complexity",{"name":425,"path":632,"isActive":110},"/technical-interview/tasks/what-is-the-algorithmic-complexity-of-quick-sort",{"title":634,"list":635,"isOpened":110},"Дебаггинг",[636],{"name":401,"path":637,"isActive":110},"/technical-interview/tasks/how-can-diagnose-and-fix-unwanted-background-color-changes-when-clicking-on-a-button-if-the-source-code-of-the-site-is-confusing-and-inaccessible-to-direct-reading",{"title":639,"list":640,"isOpened":110},"Компьютерные сети",[641,643,645,647,649,651,653,655,657,659,661,663,665,667,669,671,673,675,677,679],{"name":248,"path":642,"isActive":110},"/technical-interview/tasks/how-does-the-browser-know-where-to-get-the-website-after-entering-the-domain",{"name":452,"path":644,"isActive":110},"/technical-interview/tasks/what-is-dns-and-how-does-dns-find-the-correct-ip-address",{"name":251,"path":646,"isActive":110},"/technical-interview/tasks/how-does-a-domain-get-into-the-dns-mapping-table-domain-ip",{"name":254,"path":648,"isActive":110},"/technical-interview/tasks/how-does-a-browser-decide-whether-to-open-a-tcp-or-udp-connection",{"name":257,"path":650,"isActive":110},"/technical-interview/tasks/key-differences-between-tcp-and-udp",{"name":260,"path":652,"isActive":110},"/technical-interview/tasks/tcp-ip-who-is-tcp-and-who-is-ip-in-this-case",{"name":263,"path":654,"isActive":110},"/technical-interview/tasks/what-is-http-and-what-does-it-consist-of",{"name":266,"path":656,"isActive":110},"/technical-interview/tasks/what-are-http-headers-and-why-do-we-need-them",{"name":269,"path":658,"isActive":110},"/technical-interview/tasks/what-are-http-parameters",{"name":272,"path":660,"isActive":110},"/technical-interview/tasks/where-is-the-html-code-located-in-the-http-response-structure",{"name":278,"path":662,"isActive":110},"/technical-interview/tasks/what-are-the-differences-between-http-versions-1-0-1-1-2-0-and-3-0",{"name":281,"path":664,"isActive":110},"/technical-interview/tasks/the-user-is-logged-in-on-the-website-how-does-the-server-know-that-i-am-an-authorized-user-when-the-user-logs-in-again",{"name":284,"path":666,"isActive":110},"/technical-interview/tasks/what-is-a-cookie",{"name":287,"path":668,"isActive":110},"/technical-interview/tasks/who-initiates-the-cookie-recording-in-the-browser",{"name":290,"path":670,"isActive":110},"/technical-interview/tasks/is-it-possible-to-manage-cookies-from-the-client-browser",{"name":449,"path":672,"isActive":110},"/technical-interview/tasks/is-it-true-that-an-attacker-who-controls-a-router-and-listens-to-traffic-can-obtain-logins-and-passwords-from-websites-that-a-client-visits",{"name":299,"path":674,"isActive":110},"/technical-interview/tasks/is-everything-that-goes-through-https-secure",{"name":302,"path":676,"isActive":110},"/technical-interview/tasks/all-data-is-encrypted-https-is-used-let-s-assume-a-hacker-hacks-the-dns-and-makes-a-substitution-of-one-ip-for-another-a-phishing-site",{"name":305,"path":678,"isActive":110},"/technical-interview/tasks/there-is-a-web-application-in-addition-to-http-what-other-protocols-of-the-same-level-application-layer-can-be-used-in-the-web-application-in-browser",{"name":431,"path":680,"isActive":110},"/technical-interview/tasks/how-can-a-user-be-authorized-on-a-website",{"title":682,"list":683,"isOpened":110},"Отрисовка в браузере",[684,686,688,690,692,694],{"name":311,"path":685,"isActive":110},"/technical-interview/tasks/what-happens-when-http-sends-html-what-does-the-browser-do-with-this-html-given-that-it-is-valid",{"name":308,"path":687,"isActive":110},"/technical-interview/tasks/how-the-browser-parses-javascript-and-images-when-rendering",{"name":314,"path":689,"isActive":110},"/technical-interview/tasks/what-is-blocking-the-page-rendering-in-the-browser",{"name":317,"path":691,"isActive":110},"/technical-interview/tasks/what-is-dom-in-a-browser-what-is-cssom",{"name":320,"path":693,"isActive":110},"/technical-interview/tasks/what-are-nodes-in-the-dom",{"name":323,"path":695,"isActive":110},"/technical-interview/tasks/what-does-cssom-consist-of",{"title":697,"list":698,"isOpened":110},"Ревью кода",[699],{"name":413,"path":700,"isActive":110},"/technical-interview/tasks/how-does-a-reviewer-know-which-code-is-good-and-which-code-is-bad",{"title":702,"list":703,"isOpened":110},"Теория вероятности",[704,706,708],{"name":437,"path":705,"isActive":110},"/technical-interview/tasks/there-are-three-people-in-the-room-what-is-the-probability-that-at-least-two-of-them-are-of-the-same-sex-that-is-two-or-more",{"name":440,"path":707,"isActive":110},"/technical-interview/tasks/there-is-a-coin-it-is-tossed-five-times-in-a-row-each-time-it-is-recorded-whether-it-lands-on-heads-or-tails-how-many-different-sequences-of-heads-and-tails-can-be-obtained",{"name":443,"path":709,"isActive":110},"/technical-interview/tasks/how-can-you-guarantee-to-find-an-easy-fake-coin-among-8-in-the-minimum-number-of-weighings-on-a-balance-scale",{"cooperation":711,"copyright":714,"reportError":715,"socialNetwork":717},{"link":712,"title":713},"https://t.me/baurinanton","Сотрудничество","© “GOOD WEB JOB!”",{"label":716,"link":712},"Сообщить об ошибке",{"label":718,"socialNetworkList":719},"Мы в соцсетях:",[720,723,726],{"icon":58,"link":721,"title":722},"https://max.ru/u/f9LHodD0cOKMaukdnnahTeL5pwvjrPfUaZ4S8_1rsNy9I9qsmc9Ar3kP_y8","Max",{"icon":724,"link":712,"title":725},"ic:baseline-telegram","Telegram",{"icon":727,"link":728,"title":729},"ri:vk-fill","https://vk.com/baurinanton","VK",{"data":731,"body":732},{},{"type":733,"children":734},"root",[735],{"type":736,"tag":737,"props":738,"children":739},"element","p",{},[740],{"type":741,"value":122},"text",{"data":743,"body":744},{},{"type":733,"children":745},[746],{"type":736,"tag":737,"props":747,"children":748},{},[749],{"type":741,"value":109},{"data":751,"body":752},{},{"type":733,"children":753},[754],{"type":736,"tag":737,"props":755,"children":756},{},[757],{"type":741,"value":113},{"data":759,"body":760},{},{"type":733,"children":761},[762],{"type":736,"tag":737,"props":763,"children":764},{},[765],{"type":741,"value":116},{"data":767,"body":768},{},{"type":733,"children":769},[770],{"type":736,"tag":737,"props":771,"children":772},{},[773],{"type":741,"value":119},{"data":775,"body":776},{},{"type":733,"children":777},[778,783,830],{"type":736,"tag":737,"props":779,"children":780},{},[781],{"type":741,"value":782},"Если хранится единый объект:",{"type":736,"tag":784,"props":785,"children":786},"ul",{},[787,798,809],{"type":736,"tag":788,"props":789,"children":790},"li",{},[791],{"type":736,"tag":792,"props":793,"children":795},"code",{"className":794},[],[796],{"type":741,"value":797},"GlobalProvider value={{ user, settings, cart, ... }}",{"type":736,"tag":788,"props":799,"children":800},{},[801,803],{"type":741,"value":802},"изменился ",{"type":736,"tag":792,"props":804,"children":806},{"className":805},[],[807],{"type":741,"value":808},"cart",{"type":736,"tag":788,"props":810,"children":811},{},[812,814,820,822,828],{"type":741,"value":813},"обновились все потребители ",{"type":736,"tag":792,"props":815,"children":817},{"className":816},[],[818],{"type":741,"value":819},"user/settings/cart/...",{"type":741,"value":821},", потому что поменялась ссылка на объект ",{"type":736,"tag":792,"props":823,"children":825},{"className":824},[],[826],{"type":741,"value":827},"value",{"type":741,"value":829}," (или его часть была пересобрана)",{"type":736,"tag":831,"props":832,"children":836},"pre",{"className":833,"code":835,"language":741},[834],"language-text","UI components\n   |\n   v  useContext(GlobalStateContext)\n[consumer A: user]   [consumer B: cart]   [consumer C: settings]\n        \\                 |                 /\n         \\                |                /\n          +---- Provider value changed ----+\n",[837],{"type":736,"tag":792,"props":838,"children":840},{"__ignoreMap":839},"",[841],{"type":741,"value":835},{"data":843,"body":844},{},{"type":733,"children":845},[846,851],{"type":736,"tag":737,"props":847,"children":848},{},[849],{"type":741,"value":850},"При выборе между «React-only» и менеджером состояния удобно проверять три вопроса:",{"type":736,"tag":852,"props":853,"children":854},"ol",{},[855,860,865],{"type":736,"tag":788,"props":856,"children":857},{},[858],{"type":741,"value":859},"Сколько независимых частей состояния должно жить «вне» конкретного компонента?",{"type":736,"tag":788,"props":861,"children":862},{},[863],{"type":741,"value":864},"Насколько важно, чтобы обновления были селективными (подписка на малый фрагмент)?",{"type":736,"tag":788,"props":866,"children":867},{},[868],{"type":741,"value":869},"Нужны ли стандартные паттерны для асинхронности и развитая отладка?",{"data":871,"body":872},{},{"type":733,"children":873},[874],{"type":736,"tag":737,"props":875,"children":876},{},[877,883],{"type":736,"tag":878,"props":879,"children":880},"strong",{},[881],{"type":741,"value":882},"Правильный ответ: 3",{"type":741,"value":884}," - Специализированные библиотеки управления состоянием (Redux, Effector) решают фундаментальные проблемы масштабирования приложений: обеспечивают предсказуемость обновлений через однонаправленный поток данных, оптимизируют производительность через точечные подписки на изменения, предоставляют стандартизированные паттерны для асинхронных операций и мощные инструменты для отладки, что критично для крупных проектов с командной разработкой.",{"data":886,"body":887},{},{"type":733,"children":888},[889,918],{"type":736,"tag":737,"props":890,"children":891},{},[892,894,900,902,908,910,916],{"type":741,"value":893},"Централизованное состояние на механизмах React обычно строится из ",{"type":736,"tag":792,"props":895,"children":897},{"className":896},[],[898],{"type":741,"value":899},"useState",{"type":741,"value":901},"/",{"type":736,"tag":792,"props":903,"children":905},{"className":904},[],[906],{"type":741,"value":907},"useReducer",{"type":741,"value":909}," + ",{"type":736,"tag":792,"props":911,"children":913},{"className":912},[],[914],{"type":741,"value":915},"Context",{"type":741,"value":917},". Такой подход работает, но упирается в две практические границы: (1) стоимость ререндеров и «ширина» обновлений, (2) сложность организации логики (асинхронность, кэширование, конкурентные обновления, согласованность данных между экранами).",{"type":736,"tag":737,"props":919,"children":920},{},[921,923,927],{"type":741,"value":922},"Контекст — это механизм доставки значения «глубоко вниз», но не полноценный механизм «селективных подписок». При изменении значения контекста типичный эффект — обновления всех компонентов, которые читают этот контекст.",{"type":736,"tag":924,"props":925,"children":926},"br",{},[],{"type":741,"value":928},"\nЭто означает, что «одно большое глобальное значение» в контексте часто превращается в «перерисовку всех потребителей при любом изменении любой части объекта».",{"data":930,"body":931},{},{"type":733,"children":932},[933],{"type":736,"tag":737,"props":934,"children":935},{},[936,938,941,943,949],{"type":741,"value":937},"В Redux-подходе (через React-Redux hooks) типовая схема заключается в том, что компонент подписывается не на весь store целиком, а на результат селектора. Перерисовка происходит только когда результат селектора изменился.",{"type":736,"tag":924,"props":939,"children":940},{},[],{"type":741,"value":942},"\nИдея в том, что компонент «зависит» не от всего глобального объекта, а от маленького результата селектора (например, ",{"type":736,"tag":792,"props":944,"children":946},{"className":945},[],[947],{"type":741,"value":948},"state.auth.userId",{"type":741,"value":950},"), поэтому обновления становятся уже и дешевле.",{"data":952,"body":953},{},{"type":733,"children":954},[955],{"type":736,"tag":737,"props":956,"children":957},{},[958],{"type":741,"value":959},"Менеджеры состояния обычно навязывают (или поощряют) явную модель изменений: «событие/экшен → обработчик → новое состояние». Это снижает количество «скрытых» связей между компонентами и помогает сопровождать код, когда логика разрастается (появляются кэш, optimistic updates, синхронизация вкладок, восстановление состояния и т.п.).",{"data":961,"body":962},{},{"type":733,"children":963},[964],{"type":736,"tag":737,"props":965,"children":966},{},[967],{"type":741,"value":968},"При использовании только React часто получается «асинхронность размазана по компонентам» (эффекты в разных местах, ручная синхронизация загрузок, гонки запросов). Менеджеры состояния обычно предлагают стандартизированные способы: middleware/эффекты/события, централизованное место для побочных эффектов и единый подход к обработке ошибок и отмен.",{"data":970,"body":971},{},{"type":733,"children":972},[973],{"type":736,"tag":737,"props":974,"children":975},{},[976],{"type":741,"value":54},{"data":978,"body":979},{},{"type":733,"children":980},[981],{"type":736,"tag":737,"props":982,"children":983},{},[984],{"type":741,"value":57},{"data":986,"body":987},{},{"type":733,"children":988},[989],{"type":736,"tag":737,"props":990,"children":991},{},[992],{"type":741,"value":65},{"data":994,"body":995},{},{"type":733,"children":996},[997,1006],{"type":736,"tag":831,"props":998,"children":1001},{"className":999,"code":1000,"language":741},[834],"import React, { createContext, useContext, useMemo, useReducer } from \"react\";\n\nconst AppStateContext = createContext(null);\n\nconst initialState = {\n  user: null,\n  cart: [],\n  settings: { theme: \"light\" },\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case \"user/set\":\n      return { ...state, user: action.payload };\n    case \"cart/add\":\n      return { ...state, cart: [...state.cart, action.payload] };\n    case \"settings/theme\":\n      return { ...state, settings: { ...state.settings, theme: action.payload } };\n    default:\n      return state;\n  }\n}\n\nexport function AppStateProvider({ children }) {\n  const [state, dispatch] = useReducer(reducer, initialState);\n\n  // Без useMemo объект будет новым на каждый render Provider,\n  // а потребители будут обновляться чаще, чем нужно.\n  const value = useMemo(() => ({ state, dispatch }), [state]);\n\n  return (\n    \u003CAppStateContext.Provider value={value}>\n      {children}\n    \u003C/AppStateContext.Provider>\n  );\n}\n\nexport function useAppState() {\n  const ctx = useContext(AppStateContext);\n  if (!ctx) throw new Error(\"Provider is missing\");\n  return ctx;\n}\n",[1002],{"type":736,"tag":792,"props":1003,"children":1004},{"__ignoreMap":839},[1005],{"type":741,"value":1000},{"type":736,"tag":737,"props":1007,"children":1008},{},[1009,1011,1017,1019,1024,1026,1029,1031,1036,1038,1044],{"type":741,"value":1010},"Проблема данного подхода в том, что ",{"type":736,"tag":792,"props":1012,"children":1014},{"className":1013},[],[1015],{"type":741,"value":1016},"state",{"type":741,"value":1018}," — один объект, и любое изменение в нём означает новое значение ",{"type":736,"tag":792,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":741,"value":827},{"type":741,"value":1025}," провайдера, а значит — обновления всех потребителей контекста, читающих этот контекст.",{"type":736,"tag":924,"props":1027,"children":1028},{},[],{"type":741,"value":1030},"\nДаже если изменения касаются только ",{"type":736,"tag":792,"props":1032,"children":1034},{"className":1033},[],[1035],{"type":741,"value":808},{"type":741,"value":1037},", компонент, читающий ",{"type":736,"tag":792,"props":1039,"children":1041},{"className":1040},[],[1042],{"type":741,"value":1043},"user",{"type":741,"value":1045},", всё равно может обновляться, потому что обновилось общее значение, которое передаётся через контекст.",{"data":1047,"body":1048},{},{"type":733,"children":1049},[1050,1063,1072],{"type":736,"tag":737,"props":1051,"children":1052},{},[1053,1055,1061],{"type":741,"value":1054},"Разделение «данные» и «dispatch» уже помогает, потому что ",{"type":736,"tag":792,"props":1056,"children":1058},{"className":1057},[],[1059],{"type":741,"value":1060},"dispatch",{"type":741,"value":1062}," обычно стабилен.",{"type":736,"tag":831,"props":1064,"children":1067},{"className":1065,"code":1066,"language":741},[834],"import React, { createContext, useContext, useMemo, useReducer } from \"react\";\n\nconst StateContext = createContext(null);\nconst DispatchContext = createContext(null);\n\nfunction reducer(state, action) { /* тот же reducer */ }\n\nexport function Provider({ children }) {\n  const [state, dispatch] = useReducer(reducer, initialState);\n\n  // Состояние меняется — потребители StateContext обновятся.\n  // Dispatch стабилен — потребители DispatchContext обычно не обновятся.\n  const memoState = useMemo(() => state, [state]);\n\n  return (\n    \u003CDispatchContext.Provider value={dispatch}>\n      \u003CStateContext.Provider value={memoState}>\n        {children}\n      \u003C/StateContext.Provider>\n    \u003C/DispatchContext.Provider>\n  );\n}\n\nexport const useAppDispatch = () => useContext(DispatchContext);\nexport const useAppState = () => useContext(StateContext);\n",[1068],{"type":736,"tag":792,"props":1069,"children":1070},{"__ignoreMap":839},[1071],{"type":741,"value":1066},{"type":736,"tag":737,"props":1073,"children":1074},{},[1075,1077,1083,1085,1090,1092,1095],{"type":741,"value":1076},"Но даже здесь все потребители ",{"type":736,"tag":792,"props":1078,"children":1080},{"className":1079},[],[1081],{"type":741,"value":1082},"StateContext",{"type":741,"value":1084}," будут обновляться при любом изменении ",{"type":736,"tag":792,"props":1086,"children":1088},{"className":1087},[],[1089],{"type":741,"value":1016},{"type":741,"value":1091},", потому что контекст не знает, «какая часть состояния нужна компоненту».",{"type":736,"tag":924,"props":1093,"children":1094},{},[],{"type":741,"value":1096},"\nИменно эту «селективность» обычно и дают менеджеры состояния через селекторы/подписки.",{"data":1098,"body":1099},{},{"type":733,"children":1100},[1101,1111,1120],{"type":736,"tag":737,"props":1102,"children":1103},{},[1104,1106,1109],{"type":741,"value":1105},"Типовой подход: компонент читает только нужный фрагмент состояния через селектор, а обновляется только при изменении результата этого селектора.",{"type":736,"tag":924,"props":1107,"children":1108},{},[],{"type":741,"value":1110},"\nОтсюда следует важное правило: селектор должен возвращать стабильные значения (например, примитивы или мемоизированные объекты), иначе можно случайно создавать «ложные изменения».",{"type":736,"tag":831,"props":1112,"children":1115},{"className":1113,"code":1114,"language":741},[834],"import React from \"react\";\nimport { useSelector, useDispatch } from \"react-redux\";\n\nexport function CartTotal() {\n  // Компонент зависит только от cart.total\n  const total = useSelector((state) => state.cart.total);\n  return \u003Cdiv>Total: {total}\u003C/div>;\n}\n\nexport function ThemeSwitch() {\n  // Компонент зависит только от settings.theme\n  const theme = useSelector((state) => state.settings.theme);\n  const dispatch = useDispatch();\n\n  return (\n    \u003Cbutton\n      onClick={() =>\n        dispatch({\n          type: \"settings/theme\",\n          payload: theme === \"light\" ? \"dark\" : \"light\",\n        })\n      }\n    >\n      Theme: {theme}\n    \u003C/button>\n  );\n}\n",[1116],{"type":736,"tag":792,"props":1117,"children":1118},{"__ignoreMap":839},[1119],{"type":741,"value":1114},{"type":736,"tag":737,"props":1121,"children":1122},{},[1123,1125,1131,1133,1139,1141,1147,1149,1152],{"type":741,"value":1124},"Если меняется ",{"type":736,"tag":792,"props":1126,"children":1128},{"className":1127},[],[1129],{"type":741,"value":1130},"settings.theme",{"type":741,"value":1132},", то ",{"type":736,"tag":792,"props":1134,"children":1136},{"className":1135},[],[1137],{"type":741,"value":1138},"CartTotal",{"type":741,"value":1140}," обычно не должен перерисовываться, потому что его зависимость (",{"type":736,"tag":792,"props":1142,"children":1144},{"className":1143},[],[1145],{"type":741,"value":1146},"state.cart.total",{"type":741,"value":1148},") не изменилась.",{"type":736,"tag":924,"props":1150,"children":1151},{},[],{"type":741,"value":1153},"\nДля контекста с единым объектом такое поведение «по умолчанию» недостижимо без дополнительных приёмов (разбиение на много контекстов, дополнительные селекторные обёртки, внешние хранилища и т.п.).",{"data":1155,"body":1156},{},{"type":733,"children":1157},[1158,1168,1177],{"type":736,"tag":737,"props":1159,"children":1160},{},[1161,1163,1166],{"type":741,"value":1162},"В effector состояние хранится в store-юнитах, которые обновляются, когда возвращается новое значение (обычно требуется иммутабельный стиль обновлений).",{"type":736,"tag":924,"props":1164,"children":1165},{},[],{"type":741,"value":1167},"\nТакже поддерживаются производные store (derived), которые вычисляются из других store и обновляются автоматически при изменениях источников.",{"type":736,"tag":831,"props":1169,"children":1172},{"className":1170,"code":1171,"language":741},[834],"import { createEvent, createStore, combine } from \"effector\";\n\nconst itemAdded = createEvent();\nconst themeChanged = createEvent();\n\nconst $cart = createStore([])\n  .on(itemAdded, (cart, item) => [...cart, item]);\n\nconst $theme = createStore(\"light\")\n  .on(themeChanged, (_, nextTheme) => nextTheme);\n\nconst $cartCount = $cart.map((cart) => cart.length);\n\n// Производное состояние (derived) собирается из других store\nconst $viewModel = combine({\n  theme: $theme,\n  cartCount: $cartCount,\n});\n",[1173],{"type":736,"tag":792,"props":1174,"children":1175},{"__ignoreMap":839},[1176],{"type":741,"value":1171},{"type":736,"tag":737,"props":1178,"children":1179},{},[1180,1182,1185],{"type":741,"value":1181},"Важная практическая идея: состояние естественно дробится на небольшие store, поэтому изменение одной части не обязано затрагивать подписчиков другой части (это достигается структурой, а не только оптимизациями).",{"type":736,"tag":924,"props":1183,"children":1184},{},[],{"type":741,"value":1186},"\nТакже становится проще выносить доменную логику из компонентов, уменьшая их связность с источниками данных.",{"data":1188,"body":1189},{},{"type":733,"children":1190},[1191],{"type":736,"tag":1192,"props":1193,"children":1194},"table",{},[1195,1224],{"type":736,"tag":1196,"props":1197,"children":1198},"thead",{},[1199],{"type":736,"tag":1200,"props":1201,"children":1202},"tr",{},[1203,1209,1214,1219],{"type":736,"tag":1204,"props":1205,"children":1206},"th",{},[1207],{"type":741,"value":1208},"Подход",{"type":736,"tag":1204,"props":1210,"children":1211},{},[1212],{"type":741,"value":1213},"Где хранится состояние",{"type":736,"tag":1204,"props":1215,"children":1216},{},[1217],{"type":741,"value":1218},"Как распространяются обновления",{"type":736,"tag":1204,"props":1220,"children":1221},{},[1222],{"type":741,"value":1223},"Типичные риски",{"type":736,"tag":1225,"props":1226,"children":1227},"tbody",{},[1228,1263,1300,1323],{"type":736,"tag":1200,"props":1229,"children":1230},{},[1231,1248,1253,1258],{"type":736,"tag":1232,"props":1233,"children":1234},"td",{},[1235,1240,1241,1246],{"type":736,"tag":792,"props":1236,"children":1238},{"className":1237},[],[1239],{"type":741,"value":899},{"type":741,"value":901},{"type":736,"tag":792,"props":1242,"children":1244},{"className":1243},[],[1245],{"type":741,"value":907},{"type":741,"value":1247}," локально",{"type":736,"tag":1232,"props":1249,"children":1250},{},[1251],{"type":741,"value":1252},"В компоненте",{"type":736,"tag":1232,"props":1254,"children":1255},{},[1256],{"type":741,"value":1257},"По дереву рендера от родителя",{"type":736,"tag":1232,"props":1259,"children":1260},{},[1261],{"type":741,"value":1262},"Дублирование состояния между ветками, сложная синхронизация",{"type":736,"tag":1200,"props":1264,"children":1265},{},[1266,1275,1280,1290],{"type":736,"tag":1232,"props":1267,"children":1268},{},[1269],{"type":736,"tag":792,"props":1270,"children":1272},{"className":1271},[],[1273],{"type":741,"value":1274},"Context + useReducer",{"type":736,"tag":1232,"props":1276,"children":1277},{},[1278],{"type":741,"value":1279},"В провайдере",{"type":736,"tag":1232,"props":1281,"children":1282},{},[1283,1285],{"type":741,"value":1284},"Потребители контекста обновляются при изменении ",{"type":736,"tag":792,"props":1286,"children":1288},{"className":1287},[],[1289],{"type":741,"value":827},{"type":736,"tag":1232,"props":1291,"children":1292},{},[1293,1295],{"type":741,"value":1294},"«Широкие» ререндеры, крупные контексты, пересоздание ",{"type":736,"tag":792,"props":1296,"children":1298},{"className":1297},[],[1299],{"type":741,"value":827},{"type":736,"tag":1200,"props":1301,"children":1302},{},[1303,1308,1313,1318],{"type":736,"tag":1232,"props":1304,"children":1305},{},[1306],{"type":741,"value":1307},"Redux (React-Redux hooks)",{"type":736,"tag":1232,"props":1309,"children":1310},{},[1311],{"type":741,"value":1312},"В store",{"type":736,"tag":1232,"props":1314,"children":1315},{},[1316],{"type":741,"value":1317},"Обновление по результату селектора",{"type":736,"tag":1232,"props":1319,"children":1320},{},[1321],{"type":741,"value":1322},"Ошибки селекторов, возврат новых объектов без мемоизации",{"type":736,"tag":1200,"props":1324,"children":1325},{},[1326,1331,1336,1341],{"type":736,"tag":1232,"props":1327,"children":1328},{},[1329],{"type":741,"value":1330},"Effector",{"type":736,"tag":1232,"props":1332,"children":1333},{},[1334],{"type":741,"value":1335},"В store-юнитах",{"type":736,"tag":1232,"props":1337,"children":1338},{},[1339],{"type":741,"value":1340},"Реактивные связи, derived store",{"type":736,"tag":1232,"props":1342,"children":1343},{},[1344],{"type":741,"value":1345},"Сложность освоения модели событий/юнитов на старте",{"data":1347,"body":1348},{},{"type":733,"children":1349},[1350],{"type":736,"tag":737,"props":1351,"children":1352},{},[1353,1355,1358],{"type":741,"value":1354},"Итого: контекст и локальный стейт позволяют централизовать состояние, но по умолчанию не дают селективных подписок и масштабируемых паттернов, из‑за чего растут перерисовки и сложность сопровождения.",{"type":736,"tag":924,"props":1356,"children":1357},{},[],{"type":741,"value":1359},"\nRedux/Effector обычно добавляют более управляемую модель обновлений, точечные реакции на изменения и зрелые практики, а селекторы (или реактивные derived-единицы) помогают обновлять только те части интерфейса, которым действительно нужно обновление.",1775735655417]