Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kenmueller/sobs

React observables
https://github.com/kenmueller/sobs

Last synced: about 2 months ago
JSON representation

React observables

Awesome Lists containing this project

README

        

# sobs

> React state management using observables. Modeled after SwiftUI. No boilerplate.

## Table of contents

- [**Install**](#install)
- [**Introduction: Observable Objects and Published**](#introduction)
- [**Environments & Environment Objects**](#environments)

## Install

**IMPORTANT: You must be using TypeScript**

`npx create-react-app {app_name} --template typescript`

```bash
npm i sobs
```

## Documentation

### Introduction: Observable Objects and Published

### **IMPORTANT: Before you start...**

In your `tsconfig.json`, set `experimentalDecorators` to `true`:

```json
{
"compilerOptions": {
"experimentalDecorators": true
}
}
```

### 1. Create an `@ObservableObject`

```tsx
import { ObservableObject } from 'sobs'

@ObservableObject
class User {
// Go to the next step
}
```

### 2. Create fields

Normal fields don't cause component updates when they change.

You must mark a field with `@Published` for components to respond to its changes.

```tsx
import { ObservableObject, Published } from 'sobs'

@ObservableObject
class User {
id: string // If this changes, components won't respond

@Published name: string // If this changes, components will update

constructor(id: string, name: string) {
this.id = id
this.name = name
}

// If you are modifying an @Published variable, you must use a regular function expression.
// Arrow functions are not allowed.
resetToDefaultName() {
this.name = '...'
}
}
```

### 3. Create a store

```tsx
import { ObservableObject, Published } from 'sobs'

@ObservableObject
class User {
id: string

@Published name: string

constructor(id: string, name: string) {
this.id = id
this.name = name
}

resetToDefaultName() {
this.name = '...'
}
}

@ObservableObject
class Store {
@Published users: User[] = []

addUser(user: User) {
// Using .push(...) on an array doesn't trigger component updates.
// You must reassign the array in order to trigger an update.
this.users = [...this.users, user]
}

deleteUser(id: string) {
this.users = this.users.filter(user => user.id !== id)
}
}
```

### 4. Create components

```tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { ObservableObject, Published, observe, newId } from 'sobs'

@ObservableObject
class User {
id: string

@Published name: string

constructor(id: string, name: string) {
this.id = id
this.name = name
}

resetToDefaultName() {
this.name = '...'
}
}

@ObservableObject
class Store {
@Published users: User[] = []

addUser(name: string) {
this.users = [
...this.users,
new User(newId(), name)
]
}

deleteUser(id: string) {
this.users = this.users.filter(user => user.id !== id)
}
}

const store = new Store()

const App = () => {
// Respond to updates in the store.
// This will only respond to field reassignments; it's shallow.
// Updating a User object in the users array won't cause an update in this component.
observe(store)

return (


store.addUser(prompt('Name')!)}>
Add user


{store.users.map(user => (

))}


)
}

const UserRow = ({ user }: { user: User }) => {
// This will respond to updates on the user object.
observe(user)

return (


{user.name}


{/* This component will respond */}
Reset to default name

store.deleteUser(user.id)}> {/* The App component is observing the store object, so this will cause an update */}
Delete


)
}

ReactDOM.render(, document.getElementById('root'))
```

### Environments & Environment Objects

Documentation coming soon