Skip to content

Commit

Permalink
chore: run prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Aug 10, 2024
1 parent d72d791 commit c472fe9
Show file tree
Hide file tree
Showing 200 changed files with 3,029 additions and 5,745 deletions.
1 change: 0 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png)


## 🚀 Project Structure

Inside of your Astro project, you'll see the following folders and files:
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/blog/what-is-state-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The last condition is very important - computational resources are limited, so w

You can talk about the state as data related by some meaning, although often we are talking about some specific cache. For example, traffic light data contains information about three light bulbs, their colors and which one is on. Semantics follows from the subject area and represents the meaning of the data: only one light bulb can be turned on at a time, and the order of their switching is strictly regulated, this information is described not by the data structure, but by the code, therefore less explicit, although no less important.

The traffic light example deduced an important distinguishing feature of state as a phenomenon, is the need for data consistency: we cannot turn on one light without turning off the other, otherwise we would get erroneous data with their unpredictable impact on the user. The property of a state to be always consistent, i.e. to contain non-contradictory data, is called [atomicity](https://en.wikipedia.org/wiki/Atomicity_(database_systems)) in database theory.
The traffic light example deduced an important distinguishing feature of state as a phenomenon, is the need for data consistency: we cannot turn on one light without turning off the other, otherwise we would get erroneous data with their unpredictable impact on the user. The property of a state to be always consistent, i.e. to contain non-contradictory data, is called [atomicity](<https://en.wikipedia.org/wiki/Atomicity_(database_systems)>) in database theory.

> [Here is the test of atomicity for a few state managers](https://github.com/artalar/state-management-specification/blob/master/src/index.test.js). Btw, React.js throws all your app away from screen if uncaught error occurs in render function, there is no way to get inconsistent state during render.
Expand Down
16 changes: 4 additions & 12 deletions docs/src/content/docs/compat/core-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@ before
import { declareAction, declareAtom, map, combine } from '@reatom/core-v1'

const add = declareAction()
const n1Atom = declareAtom(0, (on) => [
on(add, (state, value) => state + value),
])
const n2Atom = declareAtom(0, (on) => [
on(add, (state, value) => state + value),
])
const n1Atom = declareAtom(0, (on) => [on(add, (state, value) => state + value)])
const n2Atom = declareAtom(0, (on) => [on(add, (state, value) => state + value)])
const sumAtom = map(combine([n1Atom, n2Atom]), ([n1, n2]) => n1 + n2)
const rootAtom = combine({ sumAtom })
```
Expand All @@ -34,12 +30,8 @@ import { declareAction, declareAtom, combine, v3toV1 } from '@reatom/core-v1'
import { atom } from '@reatom/core'

const add = declareAction()
const n1Atom = declareAtom(0, (on) => [
on(add, (state, value) => state + value),
])
const n2Atom = declareAtom(0, (on) => [
on(add, (state, value) => state + value),
])
const n1Atom = declareAtom(0, (on) => [on(add, (state, value) => state + value)])
const n2Atom = declareAtom(0, (on) => [on(add, (state, value) => state + value)])
const sumAtom = atom((ctx) => ctx.spy(n1Atom.v3atom) + ctx.spy(n2Atom.v3atom))
const rootAtom = combine({ sumAtom: v3toV1(sumAtom) })
```
Expand Down
52 changes: 18 additions & 34 deletions docs/src/content/docs/compat/core-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,10 @@ import { createAtom } from '@reatom/core-v2'
type TimerCtx = { intervalId?: number | NodeJS.Timer | any }

/** Timer update interval */
export const intervalAtom = createAtom(
{ setSeconds: (seconds: number) => seconds },
({ onAction }, state = 1000) => {
onAction(`setSeconds`, (seconds) => (state = seconds * 1000))
return state
},
)
export const intervalAtom = createAtom({ setSeconds: (seconds: number) => seconds }, ({ onAction }, state = 1000) => {
onAction(`setSeconds`, (seconds) => (state = seconds * 1000))
return state
})

export const timerAtom = createAtom(
{
Expand All @@ -239,10 +236,7 @@ export const timerAtom = createAtom(

if (remains <= interval) {
clearInterval(ctx.intervalId)
ctx.intervalId = setTimeout(
() => dispatch(create(`_update`, 0)),
remains,
)
ctx.intervalId = setTimeout(() => dispatch(create(`_update`, 0)), remains)
}

dispatch(create(`_update`, remains))
Expand Down Expand Up @@ -318,10 +312,7 @@ But a better way is use the `createEnumAtom`.
```ts
import { createEnumAtom } from '@reatom/core-v2/primitives'

const githubRepoSortFilterAtom = createEnumAtom(
['full_name', 'created', 'updated', 'pushed'],
{ format: 'snake_case' },
)
const githubRepoSortFilterAtom = createEnumAtom(['full_name', 'created', 'updated', 'pushed'], { format: 'snake_case' })

console.log(sortFilterAtom.getState())
// -> 'full_name'
Expand Down Expand Up @@ -462,11 +453,7 @@ const formAtom = createAtom(
// you should't call `track.get` async
// (scheduled callback calls async after all atoms)
// (use `email` and `password` variables instead)
track.create(
'_fetch',
track.get('emailAtom'),
track.get('passwordAtom'),
),
track.create('_fetch', track.get('emailAtom'), track.get('passwordAtom')),
),
)
})
Expand Down Expand Up @@ -540,21 +527,18 @@ const counterAtom = createAtom({ inc: () => {} }, ({ onAction }, state = 0) => {
Important note. Feel free to mutate **variable**, not a value. Reducer functions should not mutate any input values.

```ts
const counterAtom = createAtom(
{ inc: () => {} },
({ onAction }, state = { count: 0 }) => {
// WRONG
onAction('inc', () => {
state.count++
})
// Right
onAction('inc', () => {
state = { count: state.count + 1 }
})
const counterAtom = createAtom({ inc: () => {} }, ({ onAction }, state = { count: 0 }) => {
// WRONG
onAction('inc', () => {
state.count++
})
// Right
onAction('inc', () => {
state = { count: state.count + 1 }
})

return state
},
)
return state
})
```

### How to handle one action in a few atoms?
Expand Down
2 changes: 0 additions & 2 deletions docs/src/content/docs/compat/react-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ description: Reatom for react-v1
<!-- DO NOT EDIT THIS FILE -->
<!-- CHECK "packages/*/README.md" -->



This is compatible package which allow you to use `@reatom/core-v1` with react. All docs is [here](/package/npm-react/).

## Setup batching for old React
Expand Down
10 changes: 2 additions & 8 deletions docs/src/content/docs/compat/react-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ const [data] = useAtom(dataAtom)
#### Depended value by selector

```ts
const [propAtom] = useMemo(
() => createAtom({ dataAtom }, ({ get }) => get('dataAtom')[props.id]),
[props.id],
)
const [propAtom] = useMemo(() => createAtom({ dataAtom }, ({ get }) => get('dataAtom')[props.id]), [props.id])
const [propValue] = useAtom(propAtom)
```

Expand All @@ -82,10 +79,7 @@ const handleUpdateData = useAction(dataAtom.update)
#### Prepare payload for dispatch

```ts
const handleUpdateData = useAction(
(value) => dataAtom.update({ id: props.id, value }),
[props.id],
)
const handleUpdateData = useAction((value) => dataAtom.update({ id: props.id, value }), [props.id])
```

#### Conditional dispatch
Expand Down
4 changes: 1 addition & 3 deletions docs/src/content/docs/getting-started/learning.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ export const todoAtom = atom(null)
export const isLoadingAtom = atom(false)

export const fetchTodo = action(async (ctx) => {
const response = await ctx.schedule(() =>
fetch('https://jsonplaceholder.typicode.com/todos/1'),
)
const response = await ctx.schedule(() => fetch('https://jsonplaceholder.typicode.com/todos/1'))
return await response.json()
})

Expand Down
12 changes: 5 additions & 7 deletions docs/src/content/docs/getting-started/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ The base template project includes Vite, TypeScript, React and Reatom ecosystem.
You can check in out [here](https://github.com/artalar/reatom-react-ts)

You can also try it online:
- [codesandbox](https://codesandbox.io/p/sandbox/github/artalar/reatom-react-ts/tree/main)
- [stackblitz](https://githubblitz.com/artalar/reatom-react-ts)
- [gitpod](https://gitpod.io/#https://github.com/artalar/reatom-react-ts)

- [codesandbox](https://codesandbox.io/p/sandbox/github/artalar/reatom-react-ts/tree/main)
- [stackblitz](https://githubblitz.com/artalar/reatom-react-ts)
- [gitpod](https://gitpod.io/#https://github.com/artalar/reatom-react-ts)

To setup it in your machine you can use the [degit](https://github.com/Rich-Harris/degit) package.

Expand Down Expand Up @@ -90,10 +91,7 @@ const nameAtom = atom('Joe')
const Greeting = () => {
const t = useTranslation()
const [name, setName] = useAtom(nameAtom)
const [greeting] = useAtom(
(ctx) => `${t('common:GREETING')} ${ctx.spy(nameAtom)}!`,
[t],
)
const [greeting] = useAtom((ctx) => `${t('common:GREETING')} ${ctx.spy(nameAtom)}!`, [t])

return (
<>
Expand Down
14 changes: 7 additions & 7 deletions docs/src/content/docs/getting-started/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ In the next example, we have an async API.
import { action, atom } from '@reatom/core'

export const todoAtom = atom(null)
export const isLoadingAtom = atom(false);
export const isLoadingAtom = atom(false)

export const fetchTodo = action(async (ctx) => {
const response = await ctx.schedule(() => fetch('https://jsonplaceholder.typicode.com/todos/1'))
return await response.json();
return await response.json()
})

export const loadTodo = action(async (ctx) => {
try {
isLoadingAtom(ctx, true)
const data = await ctx.schedule((ctx) => fetchTodo(ctx))
todoAtom(ctx, data);
todoAtom(ctx, data)
} catch (e) {
console.error(e)
} finally {
Expand All @@ -80,13 +80,13 @@ export const loadTodo = action(async (ctx) => {
Let's test it without calling the real api

```js
import { expect, test } from 'vitest';
import { createTestCtx } from '@reatom/testing';
import { loadTodo, fetchTodo, todoAtom } from './main';
import { expect, test } from 'vitest'
import { createTestCtx } from '@reatom/testing'
import { loadTodo, fetchTodo, todoAtom } from './main'

test('Test loadData atom', async () => {
const ctx = createTestCtx()
const track = ctx.subscribeTrack(todoAtom)
const track = ctx.subscribeTrack(todoAtom)

// Mock action with call
ctx.mockAction(fetchTodo, (ctx) => Promise.resolve([{ id: 'foo' }]))
Expand Down
17 changes: 6 additions & 11 deletions docs/src/content/docs/handbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ Most likely you will need [@reatom/npm-react](/package/npm-react/) adapter packa

> The "npm-" prefix in adapter packages prevents naming collisions with ecosystem packages, as the NPM global namespace is widely used, and many common words are already taken.

```sh
npm i @reatom/framework @reatom/testing @reatom/eslint-plugin @reatom/npm-react
```
Expand Down Expand Up @@ -110,8 +109,9 @@ Reactive programming can address these issues by accurately describing dependent
Let's refactor the code using Reatom.

We use the `atom` function to wrap our changeable data:
- If you pass a primitive value to the atom, it allows the state to change.
- If you pass a `computer` function to the atom, it creates a read-only atom that automatically recomputes when dependent atoms change, but only if the computed atom has a subscription.

- If you pass a primitive value to the atom, it allows the state to change.
- If you pass a `computer` function to the atom, it creates a read-only atom that automatically recomputes when dependent atoms change, but only if the computed atom has a subscription.

```ts
export const nameAtom = atom(localStorage.getItem('name') ?? '')
Expand Down Expand Up @@ -215,9 +215,7 @@ export const submit = action(async (ctx, event) => {
const body = new FormData()
body.append('name', name)

const response = await ctx.schedule(() =>
fetch('/api/submit', { method: 'POST', body: body }),
)
const response = await ctx.schedule(() => fetch('/api/submit', { method: 'POST', body: body }))
if (!response.ok) {
alert(`Oups, the API is doesn't exist, this is just a test.`)
}
Expand Down Expand Up @@ -261,10 +259,7 @@ export const pageAtom = atom(1, 'pageAtom').pipe(
export const issuesReaction = reatomResource(async (ctx) => {
const page = ctx.spy(pageAtom)
return await ctx.schedule(() =>
request<IssuesResponse>(
`https://api.github.com/search/issues?q=reatom&page=${page}&per_page=10`,
ctx.controller,
),
request<IssuesResponse>(`https://api.github.com/search/issues?q=reatom&page=${page}&per_page=10`, ctx.controller),
)
}, 'issuesReaction').pipe(withDataAtom({ items: [] }))

Expand Down Expand Up @@ -314,7 +309,7 @@ To view persisted actions data and explore many more features, try [reatom/logge
Additionally, you can inspect all atom and action patches by using:

```javascript
ctx.subscribe(logs => console.log(logs));
ctx.subscribe((logs) => console.log(logs))
```

## Lifecycle
Expand Down
17 changes: 6 additions & 11 deletions docs/src/content/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ description: Reatom - tiny and powerful reactive system with immutable nature
- **smallest bundle** size: [2 KB](https://bundlejs.com/?q=%40reatom%2Fcore) gzipped
<small>With the power of base primitives, the whole ecosystem with <strong>A&nbsp;LOT</strong> of enterprise-level helpers takes only [~15KB](https://bundlejs.com/?q=%40reatom%2Fframework%2C%40reatom%2Fnpm-react%2C%40reatom%2Fpersist-web-storage%2C%40reatom%2Fundo%2C%40reatom%2Fform-web&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22use-sync-external-store%22%5D%7D%7D). Insane!</small>
- **the best TypeScript** experience
<small>[Type inference](/recipes/typescript/) is one of the main priorities for Reatom.</small>
<small>[Type inference](/recipes/typescript/) is one of the main priorities for Reatom.</small>

[The core package](/core) includes most of these features and, due to its minimal overhead, can be used in any project, from small libraries to large applications.

Expand Down Expand Up @@ -176,9 +176,7 @@ const fetchIssues = reatomAsync(async (ctx, query: string) => {
withRetry({
onReject(ctx, error: any, retries) {
// return delay in ms or -1 to prevent retries
return error?.message.includes('rate limit')
? 100 * Math.min(500, retries ** 2)
: -1
return error?.message.includes('rate limit') ? 100 * Math.min(500, retries ** 2) : -1
},
}),
)
Expand All @@ -205,11 +203,7 @@ export const Search = () => {

return (
<main>
<input
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
placeholder="Search"
/>
<input value={search} onChange={(e) => setSearch(e.currentTarget.value)} placeholder="Search" />
{isLoading && 'Loading...'}
<ul>
{issues.map(({ title }, i) => (
Expand All @@ -221,7 +215,7 @@ export const Search = () => {
}
```

The logic definition consists of only about 15 lines of code and is entirely independent from the the view part (React in our case). It makes it easy to test.
The logic definition consists of only about 15 lines of code and is entirely independent from the the view part (React in our case). It makes it easy to test.
Imagine the line count in other libraries!
The most impressive part is that the overhead is [less than 4KB (gzip)](https://bundlejs.com/?q=%28import%29%40reatom%2Fframework%2C%28import%29%40reatom%2Fnpm-react&treeshake=%5B%7B%0A++atom%2CcreateCtx%2ConUpdate%2CreatomAsync%2Csleep%2CwithAbort%2CwithDataAtom%2CwithRetry%2C%7D%5D%2C%5B%7B+useAtom+%7D%5D&share=MYewdgzgLgBBCmBDATsAFgQSiAtjAvDItjgBQBE5ANDOQiulruQJQDcAUKJLAGbxR0ASQgQArvAgEYyJCQwQAnmGClESlTFLAoADxoBHCckUAuOFGQBLMAHMWBAHwwA3hxhEA7oiuwIAG3h4AAdSACYAVgAGdhgAejiYABN4ACMQMRV4dxhuaFcYX3gcKQBfaURvXyJgqwA6fkE0EXFJUiN4ExodXTruSxB-QOR2HNkoMWQwQqhiiE5SmnJG4VEJCFY62uD4UhzPXzQAEWJEJjIAbQBdFip9w4x05ChSFwtkYnhbM1p-dSgALQ2AEHMDkGClW73KBoABKAhMrxyHnA8IAVvAdNo9DROsgQMhzIgwIoaONrJIHG4PDT4olxpNpik-opCtMSjACTAAQBGGDYGDBWQAN3gYFg5KskmRNIZUxgeIJAH46jhJBBELZ4HUbMB-GIUhAKB9ZjB-FYcL5WDLaUqYDyolEYAAqGAAWWIaFVNlI0SiZIRUqkztdYRYNpp5l5nFpixykLuowSMkyMBWzTWkk503gopMcCQqEwJBgYmCSU%2BHHAAFVy59SPQi%2BcaOmWutRlxZJ8AMJ6UijMQIc6kVuZiB1CtQM4kFhAA&config=%7B%22esbuild%22%3A%7B%22external%22%3A%5B%22react%22%2C%22use-sync-external-store%22%5D%7D%7D). Amazing, right?
On top of that, you’re not limited to network cache. Reatom is powerful and expressive enough to manage any state.
Expand Down Expand Up @@ -261,7 +255,7 @@ While this can be more predictable, it is certainly not optimal.
Effector's hot connections make it unfriendly for factory creation, which prevents the use of [atomization](/recipes/atomization/) patterns necessary for efficient immutability handling.
Additionally, Effector's [bundle size is 2-3 times more significant](https://bundlejs.com/?q=effector&treeshake=%5B%7BcraeteStore%2CcreateEvent%2Ccombine%7D%5D) with [worse performance](https://github.com/artalar/reactive-computed-bench).

[Zustand](https://github.com/pmndrs/zustand), [nanostores](https://github.com/nanostores/nanostores), [xstate](https://xstate.js.org), and [many other](https://gist.github.com/artalar/e5e8a7274dfdfbe9d36c9e5ec22fc650) state managers do not offer the same exceptional combination of type inference, features, bundle size, and performance that Reatom provides.
[Zustand](https://github.com/pmndrs/zustand), [nanostores](https://github.com/nanostores/nanostores), [xstate](https://xstate.js.org), and [many other](https://gist.github.com/artalar/e5e8a7274dfdfbe9d36c9e5ec22fc650) state managers do not offer the same exceptional combination of type inference, features, bundle size, and performance that Reatom provides.

### Why immutability?

Expand Down Expand Up @@ -299,6 +293,7 @@ Also, remember to check out our [atomization guide](/recipes/atomization).
### Limitations

No software is perfect, and Reatom is no exception. Here are some limitations you should be aware of:

- **Immutable Data**: While immutable data structures are great, they can impact performance. In critical situations, think carefully about your data structures. The good news is you [don't have to use normalization](/recipes/atomization).
- **Laziness**: Laziness is less obvious sometimes and might lead to missed updates. However, debugging a missing update is straightforward and often easier than dealing with hot observables' memory leaks and performance issues. We also have [hooks](/package/hooks) for hot linking.
- **Error Handling**: Currently, you can't subscribe to errors from any dependency, but we're working on it. In [reatomAsync](/package/async), passed effects are wrapped in an error handler, allowing you to manage errors, but you need to wrap them explicitly.
Expand Down
Loading

0 comments on commit c472fe9

Please sign in to comment.