Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ Types are installed automatically with the same package.
import { createState } from "veles";

function NameComponent() {
const nameState = createState("");
const name$ = createState("");
return (
<div>
<input
type="text"
name="name"
value={nameState.attribute()}
onInput={(e) => nameState.set(e.target.value)}
value={name$.attribute()}
onInput={(e) => name$.set(e.target.value)}
/>
<p>{nameState.render()}</p>
<p>{name$.render()}</p>
</div>
);
}
Expand Down
6 changes: 3 additions & 3 deletions docs/api/create-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,18 @@ import { createContext, createState } from "veles";
const exampleContext = createContext();

function App() {
const showState = createState(false);
const show$ = createState(false);
return (
<exampleContext.Provider value={5}>
<div>
<h1>Application</h1>
<NestedComponent />
<button
onClick={() => showState.update((currentValue) => !currentValue)}
onClick={() => show$.update((currentValue) => !currentValue)}
>
Toggle conditional component
</button>
{showState.render((shouldShow) =>
{show$.render((shouldShow) =>
shouldShow ? <ConditionalComponent /> : null
)}
</div>
Expand Down
18 changes: 9 additions & 9 deletions docs/api/create-state-accessing.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ When using Veles' state primitive, you can interact with it purely imperatively
Simply sets the next value. Please note that by default the state compares the values using `===` operator, and if the value is unchanged, nothing gets triggered. More on this in the [Equality and update control](./create-state-equality.html).

```jsx
const titleState = createState("hello");
titleState.set("world");
const title$ = createState("hello");
title$.set("world");
```

## `state.update`
Expand All @@ -31,8 +31,8 @@ titleState.set("world");
Updates the value based on the latest current value. This is useful when the next value depends on the previous one, but is also functionally equivalent on reading the latest value and immediately calling `.set(prevValue + 1)`.

```jsx
const counterState = createState(0);
counterState.update((currentValue) => currentValue + 1);
const counter$ = createState(0);
counter$.update((currentValue) => currentValue + 1);
```

## `state.get`
Expand All @@ -44,10 +44,10 @@ Reads the current value synchronously.
This is usually useful in event handlers and imperative code. Avoid using it for rendering, because it does not subscribe to updates and your components will end up not reactive.

```jsx
const formState = createState({ title: "", done: false });
const form$ = createState({ title: "", done: false });

function submit() {
const value = formState.get();
const value = form$.get();
saveTask(value);
}
```
Expand All @@ -59,7 +59,7 @@ function submit() {
Returns the previous value, if there was one.

```jsx
const countState = createState(0);
countState.set(1);
countState.getPrevious(); // 0
const count$ = createState(0);
count$.set(1);
count$.getPrevious(); // 0
```
28 changes: 14 additions & 14 deletions docs/api/create-state-component-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ state.track((value) => {
Subscribes to a selected part of the state and only triggers when that selected value changes.

```jsx
userState.trackSelected(
user$.trackSelected(
(user) => user.name,
(name) => {
console.log("new name", name);
Expand All @@ -56,16 +56,16 @@ userState.trackSelected(
`render` renders markup based on the current state value and updates it whenever the value changes.

```jsx
const titleState = createState("hello");
const title$ = createState("hello");

return titleState.render((title) => <p>{title}</p>);
return title$.render((title) => <p>{title}</p>);
```

If called without a callback, it renders the value directly.

```jsx
const titleState = createState("hello");
return titleState.render();
const title$ = createState("hello");
return title$.render();
```

## `state.renderSelected`
Expand All @@ -76,15 +76,15 @@ return titleState.render();
Works like `render`, but first selects a smaller piece of the state. This will make updates more atomic.

```jsx
const taskState = createState({ title: "task", completed: false });
const task$ = createState({ title: "task", completed: false });

return taskState.renderSelected((task) => task.title, (title) => <p>{title}</p>);
return task$.renderSelected((task) => task.title, (title) => <p>{title}</p>);
```

This can be used for conditionals.

```jsx
titleState.renderSelected(
title$.renderSelected(
(title) => title.length > 100,
(isTooLong) => (isTooLong ? <Warning /> : null),
);
Expand All @@ -98,17 +98,17 @@ titleState.renderSelected(
`attribute` is used for reactive DOM attributes. When the value changes, only that specific DOM Node's attribute will be changed.

```jsx
const disabledState = createState(false);
const disabled$ = createState(false);

return <button disabled={disabledState.attribute()} />;
return <button disabled={disabled$.attribute()} />;
```

You can also transform the value first.

```jsx
const widthState = createState(100);
const width$ = createState(100);

return <div style={widthState.attribute((value) => `width: ${value}px`)} />;
return <div style={width$.attribute((value) => `width: ${value}px`)} />;
```

## `state.renderEach`
Expand All @@ -119,12 +119,12 @@ return <div style={widthState.attribute((value) => `width: ${value}px`)} />;
`renderEach` is the optimized way to render arrays. It works by comparing old and new states and only making necessary DOM changes, e.g. inserting a new component into a specific position, or simply swapping 2 nodes without re-rendering anything. It wraps each individual value into the state object, which allows to avoid any unnecessary re-renders.

```jsx
const tasksState = createState([
const tasks$ = createState([
{ id: "1", title: "first" },
{ id: "2", title: "second" },
]);

return tasksState.renderEach({ key: "id" }, ({ elementState }) => {
return tasks$.renderEach({ key: "id" }, ({ elementState }) => {
return <div>{elementState.renderSelected((task) => task.title)}</div>;
});
```
Expand Down
22 changes: 11 additions & 11 deletions docs/api/create-state-deriving.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Each function with `options?` accepts an object with custom equality function li
Transforms one state into another.

```jsx
const userState = createState({ name: "Seva", age: 30 });
const nameState = userState.map((user) => user.name);
const user$ = createState({ name: "Seva", age: 30 });
const name$ = user$.map((user) => user.name);
```

## `state.filter`
Expand All @@ -30,14 +30,14 @@ const nameState = userState.map((user) => user.name);
Keeps only values that pass a predicate. If a new value does not pass, the previous passing value is retained.

```jsx
const numberState = createState(1);
const evenNumberState = numberState.filter((value) => value % 2 === 0);
const number$ = createState(1);
const evenNumber$ = number$.filter((value) => value % 2 === 0);
```

You can also access the previous source value.

```jsx
const filteredState = state.filter((value, prevValue) => {
const filtered$ = state.filter((value, prevValue) => {
return value !== prevValue;
});
```
Expand All @@ -49,8 +49,8 @@ const filteredState = state.filter((value, prevValue) => {
Accumulates values over time, similar to `reduce`, but as a reactive state.

```jsx
const numberState = createState(1);
const totalState = numberState.scan((acc, value) => acc + value, 0);
const number$ = createState(1);
const total$ = number$.scan((acc, value) => acc + value, 0);
```

## `state.combine`
Expand All @@ -60,9 +60,9 @@ const totalState = numberState.scan((acc, value) => acc + value, 0);
Combines several states into a single tuple state.

```jsx
const nameState = createState("Seva");
const lastNameState = createState("Zaikov");
const fullNameState = nameState
.combine(lastNameState)
const name$ = createState("Seva");
const lastName$ = createState("Zaikov");
const fullName$ = name$
.combine(lastName$)
.map(([name, lastName]) => `${name} ${lastName}`);
```
6 changes: 3 additions & 3 deletions docs/api/create-state-equality.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Derived methods accept an `equality` option.
### `state.map`

```jsx
const parityState = numberState.map(
const parity$ = number$.map(
(value) => ({ parity: value % 2 }),
{
equality: (a, b) => a.parity === b.parity,
Expand All @@ -36,7 +36,7 @@ const parityState = numberState.map(
### `state.filter`

```jsx
const activeTaskState = taskState.filter(
const activeTask$ = task$.filter(
(task) => task.active,
{
equality: (a, b) => a.id === b.id,
Expand All @@ -47,7 +47,7 @@ const activeTaskState = taskState.filter(
### `state.scan`

```jsx
const summaryState = numberState.scan(
const summary$ = number$.scan(
(acc, value) => ({ parity: (acc.parity + value) % 2 }),
{ parity: 0 },
{
Expand Down
20 changes: 10 additions & 10 deletions docs/api/create-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ has_children: true
import { createState } from "veles";

function Counter() {
const counterState = createState(0);
const counter$ = createState(0);

return (
<div>
<button
onClick={() =>
counterState.update((currentValue) => currentValue + 1)
counter$.update((currentValue) => currentValue + 1)
}
>
+
</button>
<p>{counterState.render((value) => `counter value is ${value}`)}</p>
<p>{counter$.render((value) => `counter value is ${value}`)}</p>
</div>
);
}
Expand All @@ -54,7 +54,7 @@ function Counter() {
You can connect external sources to a state by passing a second argument to `createState`. This is mostly useful to create self-contained listeners, as they will be automatically cleaned up when the component unmounts.

```jsx
const widthState = createState(window.innerWidth, (set) => {
const width$ = createState(window.innerWidth, (set) => {
const listener = () => set(window.innerWidth);
window.addEventListener("resize", listener);

Expand All @@ -69,7 +69,7 @@ const widthState = createState(window.innerWidth, (set) => {
`createState.empty` is a public empty marker value. It can be used to create states that do not have a real value yet.

```jsx
const resultState = createState(createState.empty);
const result$ = createState(createState.empty);
```

## `state.dispose`
Expand All @@ -82,12 +82,12 @@ Disposes the current state and disconnects it from parent/child derived states.

```jsx
function FullName() {
const nameState = createState("Seva");
const lastNameState = createState("Zaikov");
const fullNameState = nameState
.combine(lastNameState)
const name$ = createState("Seva");
const lastName$ = createState("Zaikov");
const fullName$ = name$
.combine(lastName$)
.map(([name, lastName]) => `${name} ${lastName}`);

return fullNameState.render((value) => <p>{value}</p>);
return fullName$.render((value) => <p>{value}</p>);
}
```
8 changes: 4 additions & 4 deletions docs/api/portals.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ If you want to render a part of your application in a different part of the DOM,
import { Portal, useState } from "veles";

function Component() {
const showMenu = useState(false);
const show$ = useState(false);
return (
<div
onMouseOver={() => showMenu.setState(true)}
onMouseOut={() => showMenu.setState(false)}
onMouseOver={() => show$.setState(true)}
onMouseOut={() => show$.setState(false)}
>
<h1>Title</h1>
{showMenu.render((shouldShow) =>
{show$.render((shouldShow) =>
shouldShow ? (
<Portal portalNode={document.getElementById("portal")}>
<div>Component menu</div>
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/component-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ function Component({ task }) {
But in general for dynamic content you want to avoid it as much as possible and pass data wrapped in `state` and let children decide how they want to consume it. For example, the same component will look like this:

```jsx
function Component({ taskState }) {
return <div>{taskState.renderSelected(task => task.name)}</div>
function Component({ task$ }) {
return <div>{task$.renderSelected(task => task.name)}</div>
}
```

Expand Down
Loading
Loading