Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/sebbekarlsson/plicit

Reactive UI framework
https://github.com/sebbekarlsson/plicit

frontend-framework jsx reactive ui ui-framework

Last synced: about 6 hours ago
JSON representation

Reactive UI framework

Awesome Lists containing this project

README

        



Plicit


A framework for building web user interfaces with explicitly defined reactivity

---

#### Some unique features:
* You have full control over the reactivity.
> You decide if a singe property / attribute should be reactive, or if an entire component should be reactive.
* Reactivity is separated from the rendering.
> You can use reactivity "outside" of the component hierarchy.
* Asynchronous components and synchronous components are treated the same.
> You don't need to treat async components in some special way... ( No **\** needed! )

---

## Reactivity

### Explicit Reactivity
While some implicit reactivity is supported, this framework aims to provide full control over
the reactivity by giving you the ability to be explicit about it.

An example:
```tsx
const Counter = () => {
const count = signal(0)

return (


The counter is
{ computedSignal(() => {count.get()}) }
count.set(x => x + 1) }}>increment

)
}
```
> Here, we are explicitly saying the only one of the `` elements should react to changes.
> However, the dependencies are __automatically__ tracked.

---

To summarize, we explicitly define an element to be reactive by wrapping it in a function.
Dependencies of a `signal` are automatically tracked.

### Asynchronous Reactivity
Plicit has been developed with asynchronicity in mind.
Components can be async, as well as VDOM children.

#### Async Components
```tsx
const HelloWorld = async () => {
await sleep(1000); // or do an API request or something :)
return

Hello world!
;
}

const App = () => {
return




}
```
> Here, the `` component will begin rendering once the `sleep()` promise has been resolved.

You can also define a "placeholder" to render while the component is loading:
```tsx
const App = () => {
return


Please wait...}/>

}
```
> Here's a good place to put a spinner or some other cool animation!

#### Async VDOM children
```tsx
const App = () => {
return


{
asyncSignal(async () => {
await sleep(1000);
return
Hello world!

}, { fallback: () => Please wait... })
}

}
```
> This will give you a similar result as the previous example,
> but instead of an async component, we're using an async signal.

### Signals
As you might have noticed from the examples, signals are used for reactive states.
**If you're not familiar with signals**: a signal is basically a container for some data and it will automatically track other functions (or signals) who depends on it.

#### Signals in Plicit
Signals in Plicit might differ a bit from other implementations, so let's go through some examples.

##### Basic Counter
```typescript
const counter = signal(0);

// This will be triggered everytime the counter is changed.
effect(() => console.log(counter.get()))

counter.set((count) => count + 1)
```

##### Computed
There is also something called __computed signals__ in Plicit, it's just a signal that transforms the value of another signal.
```typescript
const name = signal('John Doe');

// will update everytime `name` is changed
const reversedName = computedSignal(() => Array.from(name.get()).reverse().join(''));

// A computed signal can also be defined like this:
const reversedName = signal(() => name.get().reverse(), { isComputed: true });
```

##### Async
An async signal works just like a regular signal, however it's able to be updated asynchronously.
```typescript
const products = asyncSignal(async () => {
const response = await fetch('https://somedomain.com/your/api/endpoint');
return await response.json();
});

// You can check whether or not the signal has finished, either by inspecting it's state,
// or by having another signal react to it's changes.
// However, inspecting it's state is not reactive.

// Reactive, will be triggered when the promise is resolved
const productNames = computedSignal(() => {
return (products.get() || []).map(product => product.name)
})

// Not reactive
if (products.state === ESignalState.RESOLVED) { doSomething() }

```
You can also provide a fallback value and the signal will return this value if it hasn't been resolved yet
```typescript
const products = asyncSignal(async () => {
const response = await fetch('https://somedomain.com/your/api/endpoint');
return await response.json();
}, { fallback: [] });
```

---

## Getting Started
Simply run:

npx plicit-cli myapp && cd myapp && npm i && npm run dev

Now your app should be up and running!