npm package: @revva/store
Description: _Библиотека предоставляет утилиту для удобной работы с состояниями приложения, которые реализуются нативными средствами React. Инструмент позволяет легко создавать хранилища данных или сервисов, которые можно использовать в нескольких компонентах на разны
Author: Dmitriy Zverev
Latest version: 1.0.0

# @revva/store

_Библиотека предоставляет утилиту для удобной работы с состояниями приложения,
которые реализуются нативными средствами React. Инструмент позволяет легко
создавать хранилища данных или сервисов, которые можно использовать в нескольких
компонентах на разных уровнях вложенности. Фактически утилита является обёрткой
над Context API, и избавляет от написания однообразного кода, предлагая при этом
единообразное API для хранилищ, которые шарятся на несколько компонентов._

---

-   [Использование](#использование)
-   [Примеры](#примеры)

---

## Использование

Для того, что бы создать хранилище, необходимо импортировать фабрику:

```tsx
import {createStore} from '@revva/store';
```

и вызвать её:

```tsx
const [Store, useStore] = createStore(useValue);
```

Фабрика хранилища создает кортеж из двух элементов: компонент хранилища
(`Store`) и хук для получения содержимого хранилища (`useStore`). В качестве
первого аргумента в фабрику необходимо передавать функцию-хук (`useValue`),
которая и будет, предоставлять содержимое хранилища. Эта функция вызывается
внутри компонента `Store` при каждой перересовке. Это значит, что внутри неё
можно использовать любые React-хуки, например `useState`:

```tsx
const useValue = () => React.useState();
```

Так же внутри функции-хука `useValue` возможно использовать `props`, которые
передаются в компонент `Store`, и вычислять на их основании содержимое
хранилища:

```tsx
const useValue = (props) => props.a + props.b;

const [Store] = createStore(useValue);

const element = (
    <Store a={1} b={2}>
        {
            // ...
        }
    </Store>
);
```

Содержимое хранилища можно получить двумя способами:

-   Через хук `useStore`:

    ```tsx
    const SomeComponent = () => {
        const value = useStore();
        console.log(value);
        return null;
    };
    ```

    Для того, что бы хук `useStore` можно было использовать в Ваших компонентах,
    компонент хранилища (`Store`) должен быть смонтирован выше в дереве
    компонентов:

    ```tsx
    const element = (
        <Store>
            <SomeComponent />
        </Store>
    );
    ```

    Если же компонент `Store` будет отсутствовать, то при первом же вызове
    `useStore` будет выброшена ошибка.

-   Через передачу в компонент `Store` рендер-функции:

    ```tsx
    const element = (
        <Store>
            {(value) => {
                console.log(value);
                return null;
            }}
        </Store>
    );
    ```

## Примеры

Пример использования общего хранилища в нескольких независимых компонентах:

```tsx
import React from 'react';
import {createStore} from '@revva/store';

const useMessage = () => React.useState('Hello!');
const [MessageStore, useMessageStore] = createStore(useMessage);

const Message = () => {
    const [message] = useMessageStore();
    return <div>{message}</div>;
};

const MessageInput = () => {
    const [message, setMessage] = useMessageStore();
    return (
        <input
            value={message}
            onChange={(e) => {
                setMessage(e.target.value);
            }}
        />
    );
};

const element = (
    <MessageStore>
        <Message />
        <MessageInput />
    </MessageStore>
);
```

Использование `props`, которые передаются в компонент хранилища, внутри
функции-хука, предоставляющей содержимое:

```tsx
import React from 'react';
import {createStore} from '@revva/store';

type Props = {
    defaultMessage: string;
};

const useMessage = (props: Props) => React.useState(props.defaultMessage);
const [MessageStore, useMessageStore] = createStore(useMessage);

const element = (
    <MessageStore defaultMessage="Hello!">{/* ... */}</MessageStore>
);
```

Получение содержимого хранилища в том же компоненте, в котором используется и
сам компонент хранилища:

```tsx
import React from 'react';
import {createStore} from '@revva/store';

const useMessage = () => React.useState('Hello!');
const [MessageStore, useMessageStore] = createStore(useMessage);

const element = (
    <MessageStore>
        {([message, setMessage]) => (
            <input
                value={message}
                onChange={(e) => {
                    setMessage(e.target.value);
                }}
            />
        )}
    </MessageStore>
);
```