Skip to main content

Quick Start

Welcome to the State documentation!

In this guide, we’ll create a basic To-Do App to demonstrate how to create a state driven UI using State.

Setup

Clone the example repository:

git clone <URL>

Enter to the project folder and install the dependencies:

npm i @uiless.io/state

Run the project:

npm run dev
info

Open localhost:5173 in the browser to see the project running.

Creating the TodoApp class

Inside src/state/TodoApp.js add a TodoApp class that extends State.

src/state/TodoApp.js
import { State } from '@uiless.io/state';

export class TodoApp extends State {
constructor() {}
}

Create the initial state value for TodoApp and pass it to the State constructor using super keyword.

const initialTodoApp = {
todos: [],
};

export class TodoApp extends State {
constructor() {
super(initialTodoApp);
}
}

Declare the methods for adding and removing todos.

export class TodoApp extends State {
...

addTodo = (text) => {};

removeTodo = (id) => {};
}

Add the logic to update the state using the method from the parent class this.update, it uses immer to modify the current state.

export class TodoApp extends State {
...

addTodo = (text) => {
this.update((state) => {
state.todos.push({ id: crypto.randomUUID(), text });
});
};

removeTodo = (id) => {
this.update((state) => {
state.todos = state.todos.filter((todo) => todo.id !== id);
});
};
}

The full code should look like this:

src/state/TodoApp.js
import { State } from '@uiless.io/state';

const initialTodoApp = {
todos: [],
};

export class TodoApp extends State {
constructor() {
super(initialTodoApp);
}

addTodo = (text) => {
this.update((state) => {
state.todos.push({ id: crypto.randomUUID(), text });
});
};

removeTodo = (id) => {
this.update((state) => {
state.todos = state.todos.filter((todo) => todo.id !== id);
});
};
}

Implementing the TodoApp state

Inside src/state/index.js.

src/state/index.js
import { TodoApp } from './TodoApp';

export const todoApp = new TodoApp();

The instance todoApp holds all the logic that allow you update the state in a controlled and centraliced way. It can be used and shared between any UI framework component.

Integrating with the UI

You have written all the business logic and state behavior in plain js without a UI framework. It is time to integrate it into the UI.

We are using React as UI framework for this example. Install the @uiless.io/state-react package:

npm i @uiless.io/state-react

Update the App component.

src/app.js
import { useSubscribe } from '@uiless.io/state-react';
import { todoApp } from './state';
import stateLogo from './assets/state.webp';
import './App.css';

function App() {
const { todos } = useSubscribe(todoApp);

return (
<div className="container">
<section className="hero">
<a href="https://state.uiless.io" target="_blank">
<img src={stateLogo} className="logo" alt="State logo" />
</a>
<h1>State</h1>
<p>
Edit <code>src/App.jsx</code>
</p>
<p className="text">Click on the State logo to learn more</p>
</section>
<section className="todo">
<h2>To-Do List</h2>
<p className="text">Write a text for the To-Do and press enter</p>
<input
type="text"
id="todo-input"
placeholder="Example"
onKeyDown={(event) => {
if (event.key === 'Enter') {
todoApp.addTodo(event.target.value);
event.target.value = '';
}
}}
/>
{todos.map((todo) => (
<div className="todo-card" key={todo.id}>
{todo.text}
</div>
))}
</section>
</div>
);
}

export default App;

It is time to test. Go to localhost:5173 and enter a value on the input, then press Enter.