+
Todo list:
+
+
+ {visibleTodos.length === 0 ? (
+
No tasks yet, time to relax 😉
+ ) : (
+
+ {visibleTodos.map((todo) => (
+
+ ))}
+
+ )}
+
+ );
+};
diff --git a/src/widgets/todo/ui/TodoWidget/index.ts b/src/widgets/todo/ui/TodoWidget/index.ts
new file mode 100644
index 0000000..4101b4b
--- /dev/null
+++ b/src/widgets/todo/ui/TodoWidget/index.ts
@@ -0,0 +1 @@
+export { TodoWidget } from './TodoWidget';
diff --git a/wiki/README.md b/wiki/README.md
index 2a0aa57..563a877 100644
--- a/wiki/README.md
+++ b/wiki/README.md
@@ -18,3 +18,9 @@ For product documentation (user stories, feature specs), see [docs/](../docs/REA
- [Immutable state in React](./immutable-state.md)
- [Derived state in React](./derived-state.md)
- [Feature-Sliced Design](./fsd-architecture.md)
+- [State management (overview & decision guide)](./state-management.md)
+- [Redux setup (RTK)](./redux-setup.md)
+- [Redux/RTK concepts (actions, payload, Immer)](./redux-concepts.md)
+- [State managers compared (Redux vs Zustand vs MobX)](./state-managers-comparison.md)
+- [Хуки и кастомные хуки: как это устроено внутри](./react-hooks-fundamentals.md)
+- [Composite-хук виджета (facade hook)](./widget-facade-hook.md)
diff --git a/wiki/fsd-architecture.md b/wiki/fsd-architecture.md
index 6be4e86..503bd28 100644
--- a/wiki/fsd-architecture.md
+++ b/wiki/fsd-architecture.md
@@ -210,6 +210,8 @@ src/
- **`TodoFilter` → feature `filter-todos`.** Действие — переключение фильтра.
- **`TodoList` → widget `todo-list`.** Композиция: рендерит много `TodoItem`, принимает обработчики. Для чистого переноса оставили имя `TodoList` (без переименования в `TodoBoard`).
- **`App.tsx` → page `home`.** Вся логика приложения была в `App`. По FSD page просто собирает виджеты и фичи; наш `home` собирает `todo-list` + `add-todo` + `filter-todos`. Компонент переименован `App` → `HomePage`.
+
+> **Обновление.** По code review виджет переехал в `widgets/todo` (`TodoWidget`) — вся логика экрана собрана в один composite-хук `useTodoWidget`, `AddTodoForm`/`TodoFilter` снова презентационные. `todo-list` как отдельный connected-виджет удалён. Подробности и мотивация — в [Composite-хук виджета](./widget-facade-hook.md).
- **`Todo` → `entities/todo/model/types.ts`**, **`FilterStatus` → `features/filter-todos/model/types.ts`.** Тип `Todo` принадлежит сущности, `FilterStatus` — фиче фильтрации, поэтому они разъехались по разным слоям. Старый `src/types/todo.ts` удалён.
## Типичные ошибки
diff --git a/wiki/react-hooks-fundamentals.md b/wiki/react-hooks-fundamentals.md
new file mode 100644
index 0000000..b2b2a87
--- /dev/null
+++ b/wiki/react-hooks-fundamentals.md
@@ -0,0 +1,143 @@
+# Хуки и кастомные хуки: как это устроено внутри
+
+> База, без которой composite-хук виджета ([widget-facade-hook.md](./widget-facade-hook.md)) выглядит магией. Здесь — механика: что вообще такое хук, почему у него такие странные правила, и что делает функцию «React-функцией».
+
+## Хук — это просто функция
+
+**Хук — обычная JS-функция, которая позволяет функциональному компоненту «подключиться» (hook into) к возможностям React** — состоянию, подписке на стор, контексту — без классов.
+
+До хуков (React < 16.8) это делалось только через классы (`this.state`, `this.setState`, lifecycle-методы). Хук — функциональный эквивалент того же самого.
+
+Имя `use...` (`useState`, `useSelector`, `useTodoWidget`) — это **конвенция**, а не ключевое слово языка. Никакого специального синтаксиса для «хуков» в JS/TS нет.
+
+## Два правила хуков — и почему они не произвольные
+
+1. Вызывать хук только на **верхнем уровне** — не в `if`, не в цикле, не после условного `return`.
+2. Вызывать хук только **изнутри React-функций** (компонентов или других хуков).
+
+### Механизм, который стоит за этими правилами
+
+React хранит состояние хуков компонента не по имени переменной, а **по порядковому индексу вызова** за один рендер — как простой список ячеек:
+
+```
+component.hooks = [ ]
+```
+
+При каждом рендере React проходит хуки строго по порядку вызова и либо создаёт новую ячейку (первый рендер), либо берёт существующую по **индексу**.
+
+**Рендер №1** (`filterStatus === 'active'`):
+
+```
+if (filterStatus === 'active') {
+ const extra = useAppSelector(selectTodos); // хук вызвался → ячейка [3] существует
+}
+```
+
+```
+[0] dispatch [1] visibleTodos [2] filterStatus [3] extra
+```
+
+**Рендер №2** (`filterStatus === 'all'`, условие `false`):
+
+```
+[0] dispatch [1] visibleTodos [2] filterStatus
+ (четвёртый хук не вызвался — ячейки [3] в этом рендере нет)
+```
+
+Если дальше по коду стоял ещё один хук — React попытается сопоставить его с ячейкой `[3]`, куда на самом деле раньше писал другой хук. Отсюда ошибка React: `Rendered fewer hooks than expected` / `change in the order of Hooks`.
+
+**Вывод:** правило не «нельзя `if` рядом с хуком», а точнее — **хук должен вызываться безусловно на каждом рендере**, одинаковое число раз, в одинаковом порядке. Условной может быть логика _внутри_ хука (`useEffect` может содержать `if`), но не сам факт вызова хука.
+
+Правильный фикс, если нужно «иногда» использовать значение:
+
+```ts
+const allTodos = useAppSelector(selectTodos); // всегда вызывается
+const extra = filterStatus === 'active' ? allTodos : undefined; // условие — здесь, не на хуке
+```
+
+## Что физически делает функцию «React-функцией»
+
+Тут нет типа, декоратора или спецсинтаксиса. React держит один глобальный указатель — «текущий диспетчер» (условно `currentDispatcher`), который выставляется **непосредственно перед вызовом функции компонента на рендер** и гасится сразу после:
+
+```js
+// упрощённая модель того, что происходит внутри react
+let currentDispatcher = null;
+
+function useState(initial) {
+ if (currentDispatcher === null) {
+ throw new Error('Invalid hook call');
+ }
+ return currentDispatcher.useState(initial);
+}
+
+function renderComponent(fiber) {
+ currentDispatcher = fiber.dispatcher; // ячейки ИМЕННО этого компонента
+ const result = fiber.type(fiber.props); // вызов TodoWidget()
+ currentDispatcher = null;
+ return result;
+}
+```
+
+Значит **любая** функция, вызванная синхронно, пока `currentDispatcher` выставлен, может звать хуки — не важно, вызвана она напрямую в теле компонента или на несколько уровней функций глубже. Значение имеет только момент выполнения, а не то, где функция объявлена.
+
+Отсюда: `useTodoWidget()` работает как хук, **потому что вызывается синхронно из тела `TodoWidget`**, пока React рендерит именно этот компонент:
+
+```ts
+export const TodoWidget = () => {
+ const { ... } = useTodoWidget(); // currentDispatcher ещё выставлен → хуки внутри работают
+```
+
+Если вызвать `useTodoWidget()` из `setTimeout`, из обработчика после `await`, или просто как независимую функцию вне рендера — к этому моменту `currentDispatcher === null`, и будет `Invalid hook call`.
+
+### Роль префикса `use`
+
+Раз это не рантайм-механизм — зачем вообще называть так? Для двух вещей:
+
+1. **Человека** — сигнал «внутри могут быть хуки, соблюдай правила».
+2. **`eslint-plugin-react-hooks`** (подключён в [eslint.config.js](../eslint.config.js) как `reactHooks.configs.flat.recommended`) — плагин **статически по имени** находит `use*`-функции и проверяет вызовы хуков внутри них на условность/порядок. Назови функцию иначе — плагин перестанет её проверять, и ошибку порядка вызовов линтер не поймает заранее.
+
+## Кастомный хук — просто функция, которая сама вызывает другие хуки
+
+**Кастомный хук — твоя собственная `useЧтоТо`, которая внутри вызывает другие хуки** и пакует их в переиспользуемый кусок логики. React о ней ничего не знает — для него это просто функция, которая по пути вызвала настоящие хуки.
+
+Простейший пример — [app/hooks.ts](../src/app/hooks.ts):
+
+```ts
+export const useAppDispatch = useDispatch.withTypes