Manajemen negara berorientasi layanan dengan lamp-luwak

Karena kenyataan bahwa Bereaksi menyediakan kemampuan luar biasa untuk bekerja dengan tampilan, Anda hanya dapat fokus pada pengorganisasian logika aplikasi dan semantik kode yang menjelaskan cara bekerja dengan data. Itu memilih perpustakaan manajemen negara, pilihan gaya basis kode masa depan terjadi.


Dalam artikel ini, kami akan mempertimbangkan pendekatan berbasis layanan toko diimplementasikan melalui perpustakaan lamp-luwak.


gambar lamp-luwak


TL; DR Siapa pun yang ingin segera mulai menulis kode dapat langsung beralih ke paragraf berikutnya.


Semua logika di dalam aplikasi Anda dibagi ke dalam layanan, setiap layanan berisi satu sisi, perubahan yang memberi tahu pelanggan. Layanan ini juga berisi fungsi logika di mana Anda dapat mengakses layanan lain dan menulis ulang sisi yang tidak dapat diubah, fungsi-fungsi ini dapat tidak sinkron dan mengandung efek samping.


lamp-luwak , . , React useProvide useSubscribe . , , .


, - . , embedded . .


subscribe. .



, todo- :


  • ;
  • / ;
  • /.


todos create-react-app


npx create-react-app todos --template typescript --use-npm
# or
yarn create react-app todos --template typescript

lamp-luwak todos


npm i --save lamp-luwak
# or
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, -, - .


// Todo.ts
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.


// Todo/Task.ts
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, .


// TodoCounters.ts
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.


:


gambar arsitektur layanan



App.tsx, .


List — .


// List.tsx
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 — .


// Task.tsx
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 — .


// Counters.tsx
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.


// Input.tsx
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 , .


// App.tsx
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, , . .



, .



, , , .
.




All Articles