[JavaScript] Мой стейт менеджер для React, Preact, Inferno
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Люблю изобретать велосипеды и прочие нужные предметы заново. Получается не всегда хорошо, но процесс интересный. Предлагаю вашему вниманию библиотеку управления стейтом для React, Preact (вес всего 4.8Кб). Библиотека еще находится разработке, но уже можно попробовать.Начнем с примера всеми любимого TODO органайзера. Исходный код на гитхабе.Для начала создадим основной компонент main.js.
// main.js
import React, { createElement, Component, createContext } from 'react';
import ReactDOM from 'react-dom';
import {Connect, Provider} from './store'
import Input from './InputComp'
import TodoList from './TodoList'
import LoadingComp from './LoadingComp'
const Main = () => (
<Provider>
<h1>Todo:</h1>
<LoadingComp>
<TodoList/>
</LoadingComp>
<hr/>
<Input/>
</Provider>
)
ReactDOM.render(<Main />, document.getElementById("app"));
Далее стор. Стор нам необходим для инициализации библиотеки, а также тут мы указываем все необходимые файлы с акшенсами. В нашем примере это actions.js и actionsSetup.js
// store.js
import React, { createElement, Component, createContext } from 'react';
import createStoreFactory from 'redoor';
// Экспортируем все функции из actions.js и actionsSetup.js
import * as actions from './actions'
import * as actionsSetup from './actionsSetup'
// здесь мы указываем необходимые функции библиотеки React
const createStore = createStoreFactory({
Component,
createContext,
createElement
});
// создаем стор в качестве параметра необходимо указать массив объектов
// всех используемых акшен функций
const { Provider, Connect } = createStore([
actions,
actionsSetup
]);
export { Provider, Connect };
Файл с нашими акшенсами и стейтом проекта
// actions.js
// каждый локальный стейт может содержать свой набор переменных
// redoor автоматически добавит их глобальный стор
// initState зарезервированная переменая она может быть как объект,
// так и функция, которая возвращает объект со стейтом
export const initState = {
todos:[],
value:'',
}
// добавляем в массив новую задачу
// переменная state - содержит глобальный стейт
// переменная args - зависит от передаваемых значений из компонента
// возвращает функция новые переменные стейта
export const a_enter = ({state,args}) => {
let {value,todos} = state;
todos.push({
id:(Math.random()+"").substr(2),
value:value,
done:false
});
return {
value:'',
todos
}
}
// помечаем элемент как сделанное
export const a_done = ({state,args}) => {
let {todos} = state;
let id = args.id;
todos = todos.map(it=>(it.id === id ? (it.done = !it.done, it) : it))
return {
todos
}
}
// удаляем элемент из списка
export const a_delete = ({state,args}) => {
let {todos} = state;
let id = args.id;
todos = todos.filter(it=>it.id !== id)
return {
todos
}
}
Теперь компоненты отображения
// InputComp.js
import React from 'react';
import {Connect} from './store'
// redoor добавляет в пропсы функцию cxRun и все переменные
// глобально стора
const Input = ({cxRun, value})=><label className="input">
Todo:
// здесь мы можем поменять стор прямо из компонента
<input onChange={e=>cxRun({value:e.target.value})}
value={value}
type="text"
/>
// по нажатию вызываем акшен a_enter из нашено actions.js
<button onClick={e=>cxRun('a_enter')} disabled={!value.length}>
ok
</button>
</label>
// соеденяем с redoor наш компонент и экспортируем
export default Connect(Input);
cxRun может работать в двух режимах. Первый непосредственно менять содержимое стора, как в случае ввода строки или вызова акшенса из файла actions.js.И последний компонент выводящий сам список дел.
// TodoList.js
import React from 'react';
import {Connect} from './store'
const Item = ({cxRun, it, v})=><div className="item">
// вызываем акшен a_done, где в качестве параметра указываем
// элемент массива в ашенсе эта переменная будет называться args
<div className="item_txt" onClick={e=>cxRun('a_done',it)}>
{v+1}) {it.done ? <s>{it.value}</s> : <b>{it.value}</b>}
</div>
<div className="item_del" onClick={e=>cxRun('a_delete',it)}>
×
</div>
</div>
const TodoList = ({cxRun, todos})=><div className="todos">
{
todos.map((it,v)=><Item key={v} cxRun={cxRun} it={it} v={v}/>)
}
</div>
export default Connect(TodoList);
Теперь по порядку. В нашем проекте в глобальном сторе всего две переменные value и todos. Инициализацией их занимается initState в файле actions.js. initState может быть объектом, так и функцией которая должна вернуть объект со стейтом. Тут важно понимать, что все стейты в акшенс файле помещаются в единый объект и каждый акшенс имеет доступ к любым переменным стейта. Акшенсы -- это функции которые должны начинаться с префикса "а_" или "action". Имя функции акшенса будет указываться в качестве первого параметра при вызове cxRun. В качестве входного параметра будет объект с переменными state и args.state -- это весь глобальный стейт проектаargs -- это второй параметр вызова функции cxRun. В нашем проекте при нажатии удалить мы вызываем cxRun('a_delete', it), где первым аргументом будет имя функции акшенса, а вторым сам элемент именно его мы и получаем в args.Акшенс должен вернуть новое состояние стейта, которое автоматически перерисует компоненты которые подключены к стору. Что делать если акшен работает асинхронно? Для этого нам необходимо подключить метод setState к локальным переменным файла actions.js с помощью функции bindStateMethods.
//actions.js
let __setState;
let __getState;
// подключаем методы работы со стейтом
export const bindStateMethods = (getState, setState) => {
__getState = getState;
__setState = setState;
};
export const a_setup = async ({state,args}) => {
__setState({loading:true});
let data = await loading();
__setState({
loading:false,
todos:data
})
}
Теперь при вызове акшенса "a_load", до начала загрузки появится значок загрузки, а после загрузки данных обновиться массив данных и значок загрузки будет отключен. Если внутри асинхронной функции необходимо получить глобальный стейт, можно вызвать __getState который вернет текущее состояние стейта.DebuggerДля дебагинга есть инструмент redoor-devtool. Дебаггер это сервер который слушает данные от redoor библиотеки и передает их на одностраничник по адресу localhost:8333. Таким образом дебагер может находится не только в другом браузере, но и на другой машине. Что бывает удобно особенно при разработке для мобильных.
устанавливаем redoor-devtool:
yarn add redoor-devtool
и в отдельной консоли запускаем сервер дебаг консоли
npx redoor-devtool -o
ключик "-o" откроет хром по адресу http://localhost:8333, где будет дебаггер.ЗаключениеОт себя могу поделиться, что несколько проектов я уже сделал с помощью этой библиотеки. Довольно удобно было работать с ней в проекте с сокетами. Есть конечно и особенности использования. Например, надо помнить, что все акшенсы "видны" из всех модулей. Это не будет проблемой, если иметь четкую структуру наименования акшенсов. В своих проектах использую такое именование "a_moduleName_actionName". На этом пока все. Будет интерес - постараюсь написать более подробный обзор.
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Java, Node.JS, Реверс-инжиниринг] Декомпиляция node.js в Ghidra
- [JavaScript, Функциональное программирование] Сочиняя ПО: Почему стоит изучать ФП на JavaScript? (перевод)
- [Разработка под Android, Dart, Разработка под Linux, Производство и разработка электроники, Flutter] Как портировать SDK Flutter на ТВ-приставку для разработки и запуска приложений Android TV
- [Разработка веб-сайтов, JavaScript, VueJS] Микрофронтенды: разделяй и властвуй
- [JavaScript, Программирование, ReactJS, Учебный процесс в IT] React: наглядное пособие для начинающих. Создаем свой компонент без знаний JavaScript (перевод)
- [Python, JavaScript, Программирование, Учебный процесс в IT] Ontol: подборка видео-лекций и каналов для продвинутых программистов
- [JavaScript, Медийная реклама] «Продам гараж»: фронт и реклама в hh.ru
- [Информационная безопасность, JavaScript, Google Chrome, Браузеры, Microsoft Edge] Уязвимость нулевого дня Google Chrome и Microsoft Edge опубликовали в Twitter
- [Разработка веб-сайтов, ReactJS] React Server-Side Rendering (SSR) — руководство новичка (перевод)
- [JavaScript, Программирование, Клиентская оптимизация, Математика] Кэширование данных увеличивает скорость даже в неожиданных случаях
Теги для поиска: #_javascript, #_javascript, #_state, #_manager, #_react, #_preact, #_inferno, #_javascript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 09:07
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Люблю изобретать велосипеды и прочие нужные предметы заново. Получается не всегда хорошо, но процесс интересный. Предлагаю вашему вниманию библиотеку управления стейтом для React, Preact (вес всего 4.8Кб). Библиотека еще находится разработке, но уже можно попробовать.Начнем с примера всеми любимого TODO органайзера. Исходный код на гитхабе.Для начала создадим основной компонент main.js. // main.js
import React, { createElement, Component, createContext } from 'react'; import ReactDOM from 'react-dom'; import {Connect, Provider} from './store' import Input from './InputComp' import TodoList from './TodoList' import LoadingComp from './LoadingComp' const Main = () => ( <Provider> <h1>Todo:</h1> <LoadingComp> <TodoList/> </LoadingComp> <hr/> <Input/> </Provider> ) ReactDOM.render(<Main />, document.getElementById("app")); // store.js
import React, { createElement, Component, createContext } from 'react'; import createStoreFactory from 'redoor'; // Экспортируем все функции из actions.js и actionsSetup.js import * as actions from './actions' import * as actionsSetup from './actionsSetup' // здесь мы указываем необходимые функции библиотеки React const createStore = createStoreFactory({ Component, createContext, createElement }); // создаем стор в качестве параметра необходимо указать массив объектов // всех используемых акшен функций const { Provider, Connect } = createStore([ actions, actionsSetup ]); export { Provider, Connect }; // actions.js
// каждый локальный стейт может содержать свой набор переменных // redoor автоматически добавит их глобальный стор // initState зарезервированная переменая она может быть как объект, // так и функция, которая возвращает объект со стейтом export const initState = { todos:[], value:'', } // добавляем в массив новую задачу // переменная state - содержит глобальный стейт // переменная args - зависит от передаваемых значений из компонента // возвращает функция новые переменные стейта export const a_enter = ({state,args}) => { let {value,todos} = state; todos.push({ id:(Math.random()+"").substr(2), value:value, done:false }); return { value:'', todos } } // помечаем элемент как сделанное export const a_done = ({state,args}) => { let {todos} = state; let id = args.id; todos = todos.map(it=>(it.id === id ? (it.done = !it.done, it) : it)) return { todos } } // удаляем элемент из списка export const a_delete = ({state,args}) => { let {todos} = state; let id = args.id; todos = todos.filter(it=>it.id !== id) return { todos } } // InputComp.js
import React from 'react'; import {Connect} from './store' // redoor добавляет в пропсы функцию cxRun и все переменные // глобально стора const Input = ({cxRun, value})=><label className="input"> Todo: // здесь мы можем поменять стор прямо из компонента <input onChange={e=>cxRun({value:e.target.value})} value={value} type="text" /> // по нажатию вызываем акшен a_enter из нашено actions.js <button onClick={e=>cxRun('a_enter')} disabled={!value.length}> ok </button> </label> // соеденяем с redoor наш компонент и экспортируем export default Connect(Input); // TodoList.js
import React from 'react'; import {Connect} from './store' const Item = ({cxRun, it, v})=><div className="item"> // вызываем акшен a_done, где в качестве параметра указываем // элемент массива в ашенсе эта переменная будет называться args <div className="item_txt" onClick={e=>cxRun('a_done',it)}> {v+1}) {it.done ? <s>{it.value}</s> : <b>{it.value}</b>} </div> <div className="item_del" onClick={e=>cxRun('a_delete',it)}> × </div> </div> const TodoList = ({cxRun, todos})=><div className="todos"> { todos.map((it,v)=><Item key={v} cxRun={cxRun} it={it} v={v}/>) } </div> export default Connect(TodoList); //actions.js
let __setState; let __getState; // подключаем методы работы со стейтом export const bindStateMethods = (getState, setState) => { __getState = getState; __setState = setState; }; export const a_setup = async ({state,args}) => { __setState({loading:true}); let data = await loading(); __setState({ loading:false, todos:data }) } устанавливаем redoor-devtool: yarn add redoor-devtool
npx redoor-devtool -o
=========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 25-Ноя 09:07
Часовой пояс: UTC + 5