نظرًا لحقيقة أن React يوفر إمكانات مذهلة للعمل مع العرض ، يمكنك التركيز فقط على تنظيم منطق التطبيق ودلالات الرمز التي تصف كيفية العمل مع البيانات. أولئك. اختيار مكتبة إدارة الدولة ، يتم اختيار نمط قاعدة التعليمات البرمجية المستقبلية.
في هذه المقالة ، سننظر في نهج قائم على متجر الخدمة يتم تنفيذه من خلال مكتبة lamp-luwak.

TL ؛ DR من يريد البدء في كتابة التعليمات البرمجية قريبًا يمكنه التخطي إلى الفقرة التالية.
ينقسم كل منطق داخل التطبيق الخاص بك إلى خدمات ، كل خدمة تحتوي على جانب واحد ، ويغير تغييره المشتركين. تحتوي الخدمة أيضًا على وظائف منطقية حيث يمكنك الوصول إلى خدمات أخرى وإعادة كتابة الجانب غير القابل للتغيير ، يمكن أن تكون هذه الوظائف غير متزامنة وتحتوي على آثار جانبية.
lamp-luwak , . , React useProvide useSubscribe . , , .
, - . , embedded . .
subscribe. .
, todo- :
todos create-react-app
npx create-react-app todos --template typescript --use-npm
yarn create react-app todos --template typescript
lamp-luwak todos
npm i --save lamp-luwak
yarn add lamp-luwak
, React - , - .
— -, , .
-, store.
class Todos {
store = [ ];
store . .
class TodoCounters {
todo = provide(Todo);
provide , , Todo.
React
const List = () => {
const todo = useProvide(Todo);
};
-. React useProvide, — - , Todo. , .
— , , store provide useProvide / , .
, List Todo.
services, React components .
sr/
components/ // React
Counters.tsx //
Input.tsx //
Task.tsx //
List.tsx //
services/ //
Todo/
Task.ts //
Todo.ts //
TodoCounters.ts //
App.tsx //
2- . :
Todo — , add ;TodoCounters — .
Todo , Task, .. , , . , , . , Date, Map, Set. ( SSR) , UI. , . , Task toggle, .
Task, , create, -, - .
import { create } from 'lamp-luwak';
import { Task } from './Todo/Task';
export class Todo {
store = [
create(Task, { id: 1, label: 'Cook the dinner', completed: false }),
create(Task, { id: 2, label: 'Cook the breakfast', completed: true })
]
add(label: string) {
this.store = this.store.concat(
create(Task, { id: Date.now(), label, completed: false })
);
}
}
Todo. store Task, create. add, , Task. id, Date.now.
import { subscribe, modify, action } from 'lamp-luwak';
type Store = {
id: number,
label: string,
completed: boolean
}
export const TaskChanged = action();
export class Task {
store: Store;
constructor(store: Store) {
this.store = store;
subscribe(this, TaskChanged);
}
toggle() {
modify(this).completed = !this.store.completed;
}
}
Task, . : id , label completed. toggle, , modify, , .
TaskChanged, action.
— , . , — dispatch lamp-luwak.
, , TaskChanged Task. subscribe, — , .. , — , . TaskChanged, .
import { provide, subscribe } from 'lamp-luwak';
import { Todo } from './Todo';
import { TaskChanged } from './Todo/Task';
export class TodoCounters {
todo = provide(Todo);
store = {
active: 0,
completed: 0
}
constructor() {
subscribe(this.todo, this.calculate, this);
subscribe(TaskChanged, this.calculate, this);
this.calculate();
}
calculate() {
const items = this.todo.store;
const completed = items.filter(item => item.store.completed).length;
const active = items.length - completed;
this.store = { completed, active };
}
}
TodoCounters, . 2- :
Todo, , .TaskChanged , - Task, completed, .
calculate.
:

App.tsx, .
List — .
import React from 'react';
import { useProvide } from 'lamp-luwak';
import { Todo } from '../services/Todo';
import { Task } from './Task';
export const List = () => {
const todo = useProvide(Todo);
const items = todo.store;
if (items.length === 0) return null;
return (
<ul>
{items.map(item => (
<Task task={item} key={item.store.id} />
))}
</ul>
)
};
Todo, useProvide, List, , , . , .
Task — .
import React, { FC } from 'react';
import { useSubscribe } from 'lamp-luwak';
import { Task as TaskClass } from '../services/Todo/Task';
export const Task: FC<{ task: TaskClass }> = ({ task }) => {
useSubscribe(task);
const { label, completed } = task.store;
return (
<li>
<input
className="toggle"
type="checkbox"
checked={completed}
onChange={() => task.toggle()}
/>
<span style={{
textDecoration: completed ? 'line-through' : 'none'
}}>
{label}
</span>
</li>
)
};
Task, , useSubscribe, . , toggle .
Counters — .
import React from 'react';
import { useProvide } from 'lamp-luwak';
import { TodoCounters } from '../services/TodoCounters';
export const Counters = () => {
const { active, completed } = useProvide(TodoCounters).store;
return (
<>
<div>Active: {active}</div>
<div>Completed: {completed}</div>
</>
)
};
, useProvide . , TodoCounters.
Input — .
add Todo. , Todo, React useState.
import React, { useState } from 'react';
import { useProvide } from 'lamp-luwak';
import { Todo } from '../services/Todo';
export const Input = () => {
const [text, setText] = useState('Cook the lunch');
const todo = useProvide(Todo);
const add = () => {
todo.add(text);
setText('');
};
return (
<>
<input
onChange={(e) => setText(e.target.value)}
value={text}
autoFocus
onKeyDown={(event: any) => {
if (event.keyCode === 13) add();
}}
/>
<button onClick={add}>Add</button>
</>
);
};
App.tsx, src , .
import React from 'react';
import { Input } from './components/Input';
import { List } from './components/List';
import { Counters } from './components/Counters';
const App = () => (
<>
<Input />
<List />
<Counters />
</>
);
export default App;
Enjoy! .
lamp-luwak, , . .
, .
, , , .
.