{prelegent}

Absolwent Politechniki Świętokrzyskiej i Uniwersytetu Marii Curie-Skłodowskiej. Wieloletni programista Sabre. Kiedyś: backend aplikacji internetowych; dziś: logika frontendu w aplikacjach typu SPA. Boomer, opiekun trzech kotów, przeciwnik zmian w zasadach dotyczących spalonego. Tester odporności psychicznej współpracowników.

# RUNNING APP

{app}

{komponent}

{RxDB}

{użytkownik}

klik!

.insert()

{$}

.next()

{useObservableState($)}

... obserwuje ...

... dostarcza ...
... dane ...

# FOCUS MODE

{w użyciu}

  • React
  • RxJS
  • Observable Hooks
  • RxDB, włączając w to:
    • NoSQL
    • Mongo Query
    • JSON Schema
  • create-react-app + react-scripts

{obserwable}

Pojedynczy element Wiele elementów
Pull / sync Function Iterator
Push / async Promise Observable
# FOCUS MODE

{definicja}

# FOCUS MODE

{przykład}

// RxJS

const observable = from([
  'Pierwszy', 
  'Drugi', 
  'Trzeci'
]);

observable.subscribe(it => {
  console.log(it)
})

// output:

Pierwszy
Drugi
Trzeci

{RxDB}

Stan aplikacji trzymany jest w nierelacyjnej bazie danych RxDB.

{RxAPI do PouchDB}

baza danych NoSQL

kolekcja

dokument

dokument

dokument

dokument

kolekcja

dokument

dokument

dokument

dokument

kolekcja

dokument

dokument

dokument

dokument

dokument

{RxAPI do .......}

  • PouchDB
  • Dexie.js
  • Memory
  • LokiJS
  • IndexedDB
  • SQLite
  • Worker
  • ...
# FOCUS MODE
const taskSchemaLiteral = {
    title: 'task schema',
    version: 0,
    description: 'describes task from todo list',
    primaryKey: 'id',
    type: 'object',
    properties: {
        id: {
            type: 'string',
            maxLength: 32
        },
        timestamp: {
            type: 'number'
        },
        text: {
            type: 'string'
        }
    },
    required: ['id', 'timestamp', 'text']
} as const; // <- It is important to set 'as const'
            //    to preserve the literal type

const schemaTyped = toTypedRxJsonSchema(taskSchemaLiteral);

// aggregate the document type from the schema
export type TaskType = 
  ExtractDocumentTypeFromTypedRxJsonSchema<typeof schemaTyped>;

// create the typed RxJsonSchema from the literal typed object.
export const taskSchema: RxJsonSchema<TaskType> = taskSchemaLiteral;

{JSON Schema}

# FOCUS MODE

{tworzenie bazy}

type ToDoDatabase = RxDatabase<{
    tasks: RxCollection<TaskType>
}>

// ...

const db: ToDoDatabase = await createRxDatabase({
  name: 'todo_db',
  storage: getRxStorageMemory() // adapter bazy w pamięci
});

await db.addCollections({
  tasks: {
    schema: taskSchema
  }
});
# FOCUS MODE

{dodawanie danych}

await db.tasks.bulkInsert([
  {
    id: `${Math.random()}`,
    timestamp: Date.now(),
    text: 'Example task #1'
  },
  {
    id: `${Math.random()}`,
    timestamp: Date.now(),
    text: 'Example task #2'
  }
]);

// ...

function addTask(text: string): void {
  db.tasks.insert({
    text,
    timestamp: Date.now(),
    id: `${Math.random()}`
  });
}

{komponent}

Komponent reaktowy wyświetlany w aplikacji jest zasilany danymi z RxDB, używając obserwabli oraz biblioteki Observable Hooks.

# FOCUS MODE

<App />

// index.ts

const tasks$ = db.tasks.find({
  sort: [{timestamp: 'asc'}]
}).$;

root.render(<App addTask={addTask} tasks$={tasks$}/>);

// App.tsx

type AppProps = {
    tasks$: Observable<TaskType[]>,
    addTask: (text: string) => void
}

export default function App(props: AppProps) {
    const tasks: TaskType[] | undefined = useObservableState(props.tasks$);
    // ...
    return (
        <div className="App">
            <input id={'new-task'} defaultValue={''}/>
            <input type={'button'} value={'Add task'} onClick={handler}/>
            <ul>
                {tasks?.map(it => <li key={it.id}>
                    {it.text} at {new Date(it.timestamp).toISOString()}
                </li>)}
            </ul>
        </div>
    );
}
# RUNNING APP

{czas na zabawę}

# FOCUS MODE

{copy+paste}

# FOCUS MODE

{Q+A}

React i RxDB

By Lukasz K

React i RxDB

  • 634