1.1.5 • Published 4 years ago

sobs v1.1.5

Weekly downloads
19
License
MIT
Repository
github
Last release
4 years ago

sobs

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

Table of contents

Install

IMPORTANT: You must be using TypeScript

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

npm i sobs

Documentation

Introduction: Observable Objects and Published

IMPORTANT: Before you start...

In your tsconfig.json, set experimentalDecorators to true:

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}

1. Create an @ObservableObject

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.

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

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

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 (
        <div>
            <button onClick={() => store.addUser(prompt('Name')!)}>
                Add user
            </button>
            <div>
                {store.users.map(user => (
                    <UserRow key={user.id} user={user} />
                ))}
            </div>
        </div>
    )
}

const UserRow = ({ user }: { user: User }) => {
    // This will respond to updates on the user object.
    observe(user)
    
    return (
        <div>
            <p>{user.name}</p>
            <button onClick={user.resetToDefaultName.bind(user)}> {/* This component will respond */}
                Reset to default name
            </button>
            <button onClick={() => store.deleteUser(user.id)}> {/* The App component is observing the store object, so this will cause an update */}
                Delete
            </button>
        </div>
    )
}

ReactDOM.render(<App />, document.getElementById('root'))

Environments & Environment Objects

Documentation coming soon

1.1.5

4 years ago

1.1.4

4 years ago

1.1.3

4 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago