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
klik!
.insert()
.next()
... obserwuje ...
... dostarcza ...
... dane ...
# FOCUS MODE
Pojedynczy element | Wiele elementów | |
---|---|---|
Pull / sync | Function | Iterator |
Push / async | Promise | Observable |
# FOCUS MODE
# FOCUS MODE
// RxJS
const observable = from([
'Pierwszy',
'Drugi',
'Trzeci'
]);
observable.subscribe(it => {
console.log(it)
})
// output:
Pierwszy
Drugi
Trzeci
Stan aplikacji trzymany jest w nierelacyjnej bazie danych RxDB.
baza danych NoSQL
kolekcja
dokument
dokument
dokument
dokument
kolekcja
dokument
dokument
dokument
dokument
kolekcja
dokument
dokument
dokument
dokument
dokument
# 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;
# FOCUS MODE
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
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 reaktowy wyświetlany w aplikacji jest zasilany danymi z RxDB, używając obserwabli oraz biblioteki Observable Hooks.
# FOCUS MODE
// 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
# FOCUS MODE
# FOCUS MODE