Один и тот же пакет devlink-statecore используется во всех пяти реализациях ниже. API ядра (createStore, setState, subscribe) идентичен — меняется только способ подписки под конкретный фреймворк.
Чистый JavaScript без фреймворков. Подписка на стор через store.subscribe и ручной ререндер DOM. Работает в любом браузере с поддержкой ES2020.
npm install devlink-statecore<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<title>Todo — DevLink StateCore (Vanilla)</title>
</head>
<body>
<input id="new-todo" placeholder="Новая задача" />
<button id="add">Добавить</button>
<ul id="list"></ul>
<p id="counter"></p>
<script type="module">
import { createStore } from 'devlink-statecore';
import { logger, persist } from 'devlink-statecore/middleware';
const store = createStore(
{ items: [] },
{
name: 'VanillaTodo',
middleware: [
logger({ name: 'Todo', collapsed: true }),
persist({ key: 'vanilla-todo' }),
],
},
);
const $list = document.getElementById('list');
const $counter = document.getElementById('counter');
const $input = document.getElementById('new-todo');
const $add = document.getElementById('add');
function render(state) {
$list.innerHTML = '';
state.items.forEach((t) => {
const li = document.createElement('li');
li.textContent = t.text + (t.done ? ' ✓' : '');
li.style.textDecoration = t.done ? 'line-through' : 'none';
li.addEventListener('click', () => toggle(t.id));
$list.appendChild(li);
});
$counter.textContent = 'Всего: ' + state.items.length;
}
function add() {
const text = $input.value.trim();
if (!text) return;
store.setState((s) => ({
items: [...s.items, { id: crypto.randomUUID(), text, done: false }],
}));
$input.value = '';
}
function toggle(id) {
store.setState((s) => ({
items: s.items.map((t) =>
t.id === id ? { ...t, done: !t.done } : t,
),
}));
}
store.subscribe((s) => render(s));
$add.addEventListener('click', add);
$input.addEventListener('keydown', (e) => e.key === 'Enter' && add());
render(store.getState());
</script>
</body>
</html>
Живое React-демо (Counter + Todo с persist) запущено на странице продукта.
Открыть демо →