Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@proscom/prostore-react

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@proscom/prostore-react - npm Package Compare versions

Comparing version 0.1.13 to 0.2.0

lib/es/useAsyncOperation.d.ts

1

lib/es/prostore-react.d.ts
export * from './ProstoreContext';
export * from './ProstoreSsrContext';
export * from './useAsyncOperation';
export * from './useConnectStore';

@@ -4,0 +5,0 @@ export * from './useRequestStore';

export * from './ProstoreContext';
export * from './ProstoreSsrContext';
export * from './useAsyncOperation';
export * from './useConnectStore';

@@ -4,0 +5,0 @@ export * from './useRequestStore';

2

lib/es/ProstoreContext.d.ts

@@ -11,3 +11,3 @@ /// <reference types="react" />

*/
export declare const ProstoreContext: import("react").Context<IProstoreContext>;
export declare const ProstoreContext: import("react").Context<IProstoreContext | null>;
/**

@@ -14,0 +14,0 @@ * Extracts store from the context based on the provided name,

@@ -16,5 +16,8 @@ import { useContext, createContext } from 'react';

if (typeof storeOrName === 'string') {
if (!context) {
throw new Error("ProstoreContext is not provided");
}
var store = context[storeOrName];
if (!store) {
throw new Error("Store '" + storeOrName + "' is not registered in the context");
throw new Error("Store '" + storeOrName + "' is not registered in the ProstoreContext");
}

@@ -21,0 +24,0 @@ return store;

@@ -6,3 +6,3 @@ /// <reference types="react" />

*/
export declare const ProstoreSsrContext: import("react").Context<ProstoreSsrManager>;
export declare const ProstoreSsrContext: import("react").Context<ProstoreSsrManager | null>;
export declare type IStates = {

@@ -9,0 +9,0 @@ [name: string]: any;

@@ -5,2 +5,2 @@ import { IStore } from '@proscom/prostore';

*/
export declare function useConnectStore<State>(store: IStore<State>, setState: (state: State) => any): void;
export declare function useConnectStore<State = any>(store: IStore<State>, setState: (state: State) => any): void;

@@ -5,10 +5,11 @@ import { BehaviorSubject, Observable } from 'rxjs';

*/
export declare function useObservable<State>(obs$: Observable<State>, setState: (state: State) => any): void;
export declare function useObservable<State = any>(obs$: Observable<State> | null | undefined, setState: (state: State) => any): void;
/**
* Subscribe to Observable with useState included
*/
export declare function useObservableState<State>(obs$: Observable<State>, initialState?: State): State;
export declare function useObservableState<State = any>(obs$: Observable<State> | null | undefined, initialState: State): State;
export declare function useObservableState<State = any>(obs$: Observable<State> | null | undefined): State | null;
/**
* Subscribe to BehaviorSubject
*/
export declare function useSubject<State>(sub$: BehaviorSubject<State>): State;
export declare function useSubject<State = any>(sub$: BehaviorSubject<State> | null | undefined): State | null;

@@ -7,2 +7,5 @@ import { useEffect, useState } from 'react';

useEffect(function () {
if (!obs$) {
return;
}
var sub = obs$.subscribe(function (state) {

@@ -16,5 +19,2 @@ setState(state);

}
/**
* Subscribe to Observable with useState included
*/
export function useObservableState(obs$, initialState) {

@@ -30,4 +30,5 @@ if (initialState === void 0) { initialState = null; }

export function useSubject(sub$) {
return useObservableState(sub$, sub$.value);
var _a;
return useObservableState(sub$, (_a = sub$ === null || sub$ === void 0 ? void 0 : sub$.value) !== null && _a !== void 0 ? _a : null);
}
//# sourceMappingURL=useObservable.js.map

@@ -1,14 +0,13 @@

import { DependencyList } from 'react';
import { CheckRequestResult, CheckRequestStateFn, IRequestState, IRequestStoreOptions, RequestStore } from '@proscom/prostore';
export interface UseRequestStoreResult<Vars, Data, Options> {
import { CheckRequestResult, CheckRequestStateFn, GetRequestStoreData, GetRequestStoreOptions, GetRequestStoreState, GetRequestStoreVars, RequestStore } from "@proscom/prostore";
export interface UseRequestStoreResult<Store extends RequestStore> {
check: CheckRequestResult;
state: IRequestState<Vars, Data>;
load: (options?: Options) => Promise<IRequestState<Vars, Data>>;
store: RequestStore<Vars, Data, Options>;
state: GetRequestStoreState<Store>;
load: (options?: GetRequestStoreOptions<Store>) => Promise<GetRequestStoreState<Store>>;
store: Store;
}
export interface UseRequestOptions<Vars, Data> {
export interface UseRequestOptions<Vars = any, Data = any> {
checkRequest?: CheckRequestStateFn<Vars, Data>;
}
/**
* Attached component to the provided store and requests data based on the variables and options
* Attaches component to the provided store and requests data based on the variables and options
*

@@ -22,10 +21,2 @@ * @param storeOrName - RequestStore to subscribe to, or its name for it to be injected from the context

*/
export declare function useRequestStore<Vars, Data, Options extends IRequestStoreOptions<Vars, Data>>(storeOrName: string | RequestStore<Vars, Data, Options>, variables: Vars, options?: Options, hookOptions?: UseRequestOptions<Vars, Data>): UseRequestStoreResult<Vars, Data, Options>;
/**
* The same as useRequestStore, but it uses variableCreator which is supplied to useMemo and
* can be used to memoize query variables. This may be used when the default behavior of deeply
* comparing variables is not preferable (i.e., it is not fast enough, or variables are not simple objects)
*
* @returns {{load, check, state}} - Current request state
*/
export declare function useRequestStoreVars<Vars, Data, Options extends IRequestStoreOptions<Vars, Data>>(storeOrName: string | RequestStore<Vars, Data, Options>, variableCreator: () => Vars, args: DependencyList): UseRequestStoreResult<Vars, Data, Options>;
export declare function useRequestStore<Store extends RequestStore>(storeOrName: string | Store, variables?: GetRequestStoreVars<Store> | undefined, options?: GetRequestStoreOptions<Store> | undefined, hookOptions?: UseRequestOptions<GetRequestStoreVars<Store>, GetRequestStoreData<Store>>): UseRequestStoreResult<Store>;

@@ -1,8 +0,9 @@

import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { checkRequestState, } from '@proscom/prostore';
import { useConnectStore } from './useConnectStore';
import { useContextStore } from './ProstoreContext';
import { ProstoreSsrContext } from './ProstoreSsrContext';
import { useContext, useEffect, useState } from "react";
import { checkRequestState } from "@proscom/prostore";
import { useLatestCallbackRef } from "@proscom/ui-react";
import { useConnectStore } from "./useConnectStore";
import { useContextStore } from "./ProstoreContext";
import { ProstoreSsrContext } from "./ProstoreSsrContext";
/**
* Attached component to the provided store and requests data based on the variables and options
* Attaches component to the provided store and requests data based on the variables and options
*

@@ -17,2 +18,3 @@ * @param storeOrName - RequestStore to subscribe to, or its name for it to be injected from the context

export function useRequestStore(storeOrName, variables, options, hookOptions) {
if (variables === void 0) { variables = undefined; }
if (options === void 0) { options = undefined; }

@@ -30,11 +32,6 @@ if (hookOptions === void 0) { hookOptions = {}; }

// Memoized callback to request data
var funcsRef = useRef({});
funcsRef.current.loadData = function (newOptions) {
var loadData = useLatestCallbackRef(function (newOptions) {
if (newOptions === void 0) { newOptions = undefined; }
return store.loadData(variables, newOptions || options);
};
var loadData = useCallback(function (newOptions) {
if (newOptions === void 0) { newOptions = undefined; }
return funcsRef.current.loadData(newOptions);
}, []);
});
// Request the data if it is should be requested

@@ -58,13 +55,2 @@ useEffect(function () {

}
/**
* The same as useRequestStore, but it uses variableCreator which is supplied to useMemo and
* can be used to memoize query variables. This may be used when the default behavior of deeply
* comparing variables is not preferable (i.e., it is not fast enough, or variables are not simple objects)
*
* @returns {{load, check, state}} - Current request state
*/
export function useRequestStoreVars(storeOrName, variableCreator, args) {
var variables = useMemo(variableCreator, args);
return useRequestStore(storeOrName, variables);
}
//# sourceMappingURL=useRequestStore.js.map
export * from './ProstoreContext';
export * from './ProstoreSsrContext';
export * from './useAsyncOperation';
export * from './useConnectStore';

@@ -4,0 +5,0 @@ export * from './useRequestStore';

@@ -6,2 +6,3 @@ "use strict";

tslib_1.__exportStar(require("./ProstoreSsrContext"), exports);
tslib_1.__exportStar(require("./useAsyncOperation"), exports);
tslib_1.__exportStar(require("./useConnectStore"), exports);

@@ -8,0 +9,0 @@ tslib_1.__exportStar(require("./useRequestStore"), exports);

@@ -11,3 +11,3 @@ /// <reference types="react" />

*/
export declare const ProstoreContext: import("react").Context<IProstoreContext>;
export declare const ProstoreContext: import("react").Context<IProstoreContext | null>;
/**

@@ -14,0 +14,0 @@ * Extracts store from the context based on the provided name,

@@ -19,5 +19,8 @@ "use strict";

if (typeof storeOrName === 'string') {
if (!context) {
throw new Error("ProstoreContext is not provided");
}
var store = context[storeOrName];
if (!store) {
throw new Error("Store '" + storeOrName + "' is not registered in the context");
throw new Error("Store '" + storeOrName + "' is not registered in the ProstoreContext");
}

@@ -24,0 +27,0 @@ return store;

@@ -6,3 +6,3 @@ /// <reference types="react" />

*/
export declare const ProstoreSsrContext: import("react").Context<ProstoreSsrManager>;
export declare const ProstoreSsrContext: import("react").Context<ProstoreSsrManager | null>;
export declare type IStates = {

@@ -9,0 +9,0 @@ [name: string]: any;

@@ -5,2 +5,2 @@ import { IStore } from '@proscom/prostore';

*/
export declare function useConnectStore<State>(store: IStore<State>, setState: (state: State) => any): void;
export declare function useConnectStore<State = any>(store: IStore<State>, setState: (state: State) => any): void;

@@ -5,10 +5,11 @@ import { BehaviorSubject, Observable } from 'rxjs';

*/
export declare function useObservable<State>(obs$: Observable<State>, setState: (state: State) => any): void;
export declare function useObservable<State = any>(obs$: Observable<State> | null | undefined, setState: (state: State) => any): void;
/**
* Subscribe to Observable with useState included
*/
export declare function useObservableState<State>(obs$: Observable<State>, initialState?: State): State;
export declare function useObservableState<State = any>(obs$: Observable<State> | null | undefined, initialState: State): State;
export declare function useObservableState<State = any>(obs$: Observable<State> | null | undefined): State | null;
/**
* Subscribe to BehaviorSubject
*/
export declare function useSubject<State>(sub$: BehaviorSubject<State>): State;
export declare function useSubject<State = any>(sub$: BehaviorSubject<State> | null | undefined): State | null;

@@ -10,2 +10,5 @@ "use strict";

react_1.useEffect(function () {
if (!obs$) {
return;
}
var sub = obs$.subscribe(function (state) {

@@ -20,5 +23,2 @@ setState(state);

exports.useObservable = useObservable;
/**
* Subscribe to Observable with useState included
*/
function useObservableState(obs$, initialState) {

@@ -35,5 +35,6 @@ if (initialState === void 0) { initialState = null; }

function useSubject(sub$) {
return useObservableState(sub$, sub$.value);
var _a;
return useObservableState(sub$, (_a = sub$ === null || sub$ === void 0 ? void 0 : sub$.value) !== null && _a !== void 0 ? _a : null);
}
exports.useSubject = useSubject;
//# sourceMappingURL=useObservable.js.map

@@ -1,14 +0,13 @@

import { DependencyList } from 'react';
import { CheckRequestResult, CheckRequestStateFn, IRequestState, IRequestStoreOptions, RequestStore } from '@proscom/prostore';
export interface UseRequestStoreResult<Vars, Data, Options> {
import { CheckRequestResult, CheckRequestStateFn, GetRequestStoreData, GetRequestStoreOptions, GetRequestStoreState, GetRequestStoreVars, RequestStore } from "@proscom/prostore";
export interface UseRequestStoreResult<Store extends RequestStore> {
check: CheckRequestResult;
state: IRequestState<Vars, Data>;
load: (options?: Options) => Promise<IRequestState<Vars, Data>>;
store: RequestStore<Vars, Data, Options>;
state: GetRequestStoreState<Store>;
load: (options?: GetRequestStoreOptions<Store>) => Promise<GetRequestStoreState<Store>>;
store: Store;
}
export interface UseRequestOptions<Vars, Data> {
export interface UseRequestOptions<Vars = any, Data = any> {
checkRequest?: CheckRequestStateFn<Vars, Data>;
}
/**
* Attached component to the provided store and requests data based on the variables and options
* Attaches component to the provided store and requests data based on the variables and options
*

@@ -22,10 +21,2 @@ * @param storeOrName - RequestStore to subscribe to, or its name for it to be injected from the context

*/
export declare function useRequestStore<Vars, Data, Options extends IRequestStoreOptions<Vars, Data>>(storeOrName: string | RequestStore<Vars, Data, Options>, variables: Vars, options?: Options, hookOptions?: UseRequestOptions<Vars, Data>): UseRequestStoreResult<Vars, Data, Options>;
/**
* The same as useRequestStore, but it uses variableCreator which is supplied to useMemo and
* can be used to memoize query variables. This may be used when the default behavior of deeply
* comparing variables is not preferable (i.e., it is not fast enough, or variables are not simple objects)
*
* @returns {{load, check, state}} - Current request state
*/
export declare function useRequestStoreVars<Vars, Data, Options extends IRequestStoreOptions<Vars, Data>>(storeOrName: string | RequestStore<Vars, Data, Options>, variableCreator: () => Vars, args: DependencyList): UseRequestStoreResult<Vars, Data, Options>;
export declare function useRequestStore<Store extends RequestStore>(storeOrName: string | Store, variables?: GetRequestStoreVars<Store> | undefined, options?: GetRequestStoreOptions<Store> | undefined, hookOptions?: UseRequestOptions<GetRequestStoreVars<Store>, GetRequestStoreData<Store>>): UseRequestStoreResult<Store>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useRequestStoreVars = exports.useRequestStore = void 0;
exports.useRequestStore = void 0;
var react_1 = require("react");
var prostore_1 = require("@proscom/prostore");
var ui_react_1 = require("@proscom/ui-react");
var useConnectStore_1 = require("./useConnectStore");

@@ -10,3 +11,3 @@ var ProstoreContext_1 = require("./ProstoreContext");

/**
* Attached component to the provided store and requests data based on the variables and options
* Attaches component to the provided store and requests data based on the variables and options
*

@@ -21,2 +22,3 @@ * @param storeOrName - RequestStore to subscribe to, or its name for it to be injected from the context

function useRequestStore(storeOrName, variables, options, hookOptions) {
if (variables === void 0) { variables = undefined; }
if (options === void 0) { options = undefined; }

@@ -34,11 +36,6 @@ if (hookOptions === void 0) { hookOptions = {}; }

// Memoized callback to request data
var funcsRef = react_1.useRef({});
funcsRef.current.loadData = function (newOptions) {
var loadData = ui_react_1.useLatestCallbackRef(function (newOptions) {
if (newOptions === void 0) { newOptions = undefined; }
return store.loadData(variables, newOptions || options);
};
var loadData = react_1.useCallback(function (newOptions) {
if (newOptions === void 0) { newOptions = undefined; }
return funcsRef.current.loadData(newOptions);
}, []);
});
// Request the data if it is should be requested

@@ -63,14 +60,2 @@ react_1.useEffect(function () {

exports.useRequestStore = useRequestStore;
/**
* The same as useRequestStore, but it uses variableCreator which is supplied to useMemo and
* can be used to memoize query variables. This may be used when the default behavior of deeply
* comparing variables is not preferable (i.e., it is not fast enough, or variables are not simple objects)
*
* @returns {{load, check, state}} - Current request state
*/
function useRequestStoreVars(storeOrName, variableCreator, args) {
var variables = react_1.useMemo(variableCreator, args);
return useRequestStore(storeOrName, variables);
}
exports.useRequestStoreVars = useRequestStoreVars;
//# sourceMappingURL=useRequestStore.js.map
{
"name": "@proscom/prostore-react",
"version": "0.1.13",
"version": "0.2.0",
"description": "Prostore hooks and utils for React",

@@ -29,7 +29,8 @@ "author": "Andrew Starostin <a.starostin@proscom.ru>",

"dependencies": {
"@proscom/prostore": "^0.1.13",
"@proscom/prostore": "^0.2.0",
"@proscom/ui-react": "^0.0.6",
"tslib": "^2.0.3"
},
"devDependencies": {
"@types/react": "^16.8.23",
"@types/react": "^17.0.0",
"react": "^17.0.1"

@@ -41,3 +42,3 @@ },

"sideEffects": false,
"gitHead": "3df77cce3fe186050039d517760d5c7bac7abd84"
"gitHead": "41002836cd640f25af46a1bf029b92ecf117c572"
}

@@ -15,11 +15,15 @@ # `prostore-react`

```javascript
// IncStore.js
```typescript
// IncStore.ts
import { BehaviorStore } from '@proscom/prostore';
const initialState = {
export interface IncStoreState {
number: number;
}
const initialState: IncStoreState = {
number: 0
};
export class IncStore extends BehaviorStore {
export class IncStore extends BehaviorStore<IncStoreState> {
constructor() {

@@ -37,4 +41,4 @@ super(initialState);

```javascript
// incStore.js
```typescript
// incStore.ts
import { IncStore } from './IncStore';

@@ -44,2 +48,4 @@ export const incStore = new IncStore();

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/stores/IncStore.ts)
### `useStore`

@@ -50,4 +56,4 @@

```jsx harmony
import { useStore } from '@proscom/react';
```tsx
import { useStore } from '@proscom/prostore-react';

@@ -74,2 +80,4 @@ // Импортируем любой store, расширяющий IStore

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/demo/Demo1.tsx)
### `useStoreState`

@@ -81,3 +89,3 @@

```jsx harmony
```tsx
function MyComponent() {

@@ -89,2 +97,4 @@ const state = useStoreState(incStore);

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/demo/Demo2.tsx)
### `ProstoreContext`

@@ -96,7 +106,9 @@

```jsx harmony
```typescript
// stores.ts
export const STORE_TEST = 'STORE_TEST';
```
```jsx harmony
```tsx
// index.ts
import ReactDOM from 'react-dom';

@@ -124,5 +136,6 @@ import { STORE_TEST } from './stores';

```jsx harmony
// App.js
import { useStore } from '@proscom/react';
```tsx
// App.ts
import { useStore } from '@proscom/prostore-react';
import { IncStore } from './IncStore';
import { STORE_TEST } from './stores';

@@ -133,4 +146,10 @@

// то этот вызов полностью аналогичен useStore(incStore)
const [state, store] = useStore(STORE_TEST);
// При использовании с TypeScript необходимо указать тип стора
// в качестве аргумента дженерика. Проще всего указать имя класс стора (IncStore).
// При необходимости можно уменьшить связанность кода, реализовав
// отдельный интерфейс, который реализуется классом стора, и указать
// его здесь в качестве аргумента дженерика.
const [state, store] = useStore<IncStore>(STORE_TEST);
const onClick = () => {

@@ -144,2 +163,4 @@ store.increment();

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/demo/Demo3.tsx)
### `useContextStore`

@@ -152,4 +173,5 @@

```jsx harmony
```tsx
import { incStore } from './incStore';
function IncButton() {

@@ -160,2 +182,4 @@ return <button onClick={() => incStore.increment()}>Increment</button>;

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/demo/Demo4.tsx)
При использовании контекста можно получить доступ к стору

@@ -166,7 +190,13 @@ с помощью хука `useContextStore`. По сравнению с использованием

```jsx harmony
import { useContextStore } from '@proscom/react';
```tsx
import { useContextStore } from '@proscom/prostore-react';
import { IncStore } from './IncStore';
import { STORE_TEST } from './stores';
function IncButton() {
const incStore = useContextStore(STORE_TEST);
// При использовании с TypeScript необходимо указать тип стора
// в качестве аргумента дженерика. Проще всего указать имя класс стора (IncStore).
// При необходимости можно уменьшить связанность кода, реализовав
// отдельный интерфейс, который реализуется классом стора, и указать
// его здесь в качестве аргумента дженерика.
const incStore = useContextStore<IncStore>(STORE_TEST);
return <button onClick={() => incStore.increment()}>Increment</button>;

@@ -176,2 +206,4 @@ }

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-basic-gsx5u?file=/src/demo/Demo5.tsx)
### `useRequestStore`

@@ -184,3 +216,3 @@

```jsx harmony
```tsx
import { AxiosQueryStore } from '@proscom/prostore-axios';

@@ -192,4 +224,25 @@ import { useRequestStore } from '@proscom/prostore-react';

// http-запросов с помощью axios
const store = new AxiosQueryStore(/* ... */);
// Определяем динамические параметры запроса
export interface DataQueryStoreVariables {
params?: {
page?: number;
};
}
// Определяем тип результата запроса
export interface DataQueryStoreData {
message: string;
}
// Создаём стор, который будет хранить результат запроса.
// Сам запрос вызовется, только при подключении стора в компонент
const store = new AxiosQueryStore<DataQueryStoreVariables, DataQueryStoreData>({
client: axios.create(),
query: {
url: '/data.json',
method: 'get'
}
});
function MyComponent() {

@@ -206,2 +259,4 @@ // Параметры запроса

// Подключаем стор в компонент и выполняем запрос при необходимости
// По факту выполнения запроса компонент ререндерится
const query = useRequestStore(store, variables, options);

@@ -229,2 +284,4 @@

[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-use-request-store-py67z?file=/src/demo/Demo1.tsx)
При каждом рендере `useRequestStore` **глубоко** сравнивает

@@ -239,12 +296,80 @@ предыдущие переменные с новыми, и если есть отличия, то

`useRequestStore` можно также использовать с контекстом:
`useRequestStore` можно также использовать с контекстом.
В таком случае необходимо указать тип переменных и тип результата аргументами дженерика:
```jsx harmony
```tsx
import { useRequestStore } from '@proscom/prostore-react';
import { STORE_TEST } from './stores';
import { useRequestStore } from '@proscom/prostore-react';
import { StoreTestVariables, StoreTestData } from './stores/StoreTest';
function MyComponent() {
const variables = {};
const query = useRequestStore(STORE_TEST, variables);
const query = useRequestStore<StoreTestVariables, StoreTestData>(
STORE_TEST,
variables
);
// ...
}
```
[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-use-request-store-py67z?file=/src/demo/Demo2.tsx)
### `useAsyncOperation`
`RequestStore` представляет собой реактивную зависимость результата запроса от переменных (параметров запроса).
Это значит, что момент выполнения запроса определяется автоматически.
Такая семантика подходит только запросов, удовлетворяющим свойствам чистой функции
(возвращающих одни и те же значения для одних и тех же переменных и не выполняющим побочных эффектов),
например для GET HTTP запросов на получение данных и запросов GraphQL Query.
Мутирующие запросы (POST HTTP или GraphQL Mutation) следует вызывать в коде императивно
в нужный момент (например, в ответ на клик пользователя по кнопке).
Мутирующий запрос может не оказывать никакого влияния на состояние компонентов, тогда
его можно вызывать просто напрямую без использования хуков из этой библиотеки.
Если же возникает потребность отслеживать статус выполнения мутирующего запроса, то
для этого можно использовать хук `useAsyncOperation`:
```tsx
import axios from 'axios';
import { useAsyncOperation } from '@proscom/prostore-react';
function MyComponent() {
const saveOp = useAsyncOperation(
() => {
// Чтобы корректно отследить статус завершения операции,
// колбек должен возвращать промис
return axios.post('/save', data).catch((e) => console.error(e));
// То, как обрабатывать ошибку следует решить на уровне конкретного проекта.
// Рекомендуется отобразить пользователю toast или текст ошибки рядом с кнопкой действия.
},
{
// После завершения операции ставит finished=true на 5 секунд
// Передайте Infinity, чтобы поставить finished=true навсегда после первого выполнения операции
finishedTimeout: 5000,
// Предотвращает повторный вызов операции до завершения предыдущей
singleton: true
}
);
const {
// Функция для вызова операции
run,
// true, если операция выполняется
loading,
// true, если операция недавно завершена
finished,
// позволяет поменять значение finished в сложных случаях
setFinished
} = saveOp;
return (
<button onClick={run} disabled={loading}>
{finished ? 'Saved' : loading ? 'Saving...' : 'Save'}
</button>
);
}
```
[См. пример в CodeSandbox](https://codesandbox.io/s/prostore-react-demo-async-operation-tzlhm)
export * from './ProstoreContext';
export * from './ProstoreSsrContext';
export * from './useAsyncOperation';
export * from './useConnectStore';

@@ -4,0 +5,0 @@ export * from './useRequestStore';

@@ -14,3 +14,3 @@ import { useContext, createContext } from 'react';

*/
export const ProstoreContext = createContext<IProstoreContext>(null);
export const ProstoreContext = createContext<IProstoreContext | null>(null);

@@ -29,6 +29,9 @@ /**

if (typeof storeOrName === 'string') {
if (!context) {
throw new Error(`ProstoreContext is not provided`);
}
const store = context[storeOrName];
if (!store) {
throw new Error(
`Store '${storeOrName}' is not registered in the context`
`Store '${storeOrName}' is not registered in the ProstoreContext`
);

@@ -35,0 +38,0 @@ }

@@ -7,3 +7,3 @@ import { createContext } from 'react';

*/
export const ProstoreSsrContext = createContext<ProstoreSsrManager>(null);
export const ProstoreSsrContext = createContext<ProstoreSsrManager|null>(null);

@@ -10,0 +10,0 @@ export type IStates = {

@@ -7,3 +7,3 @@ import { IStore } from '@proscom/prostore';

*/
export function useConnectStore<State>(
export function useConnectStore<State = any>(
store: IStore<State>,

@@ -10,0 +10,0 @@ setState: (state: State) => any

@@ -7,7 +7,10 @@ import { BehaviorSubject, Observable } from 'rxjs';

*/
export function useObservable<State>(
obs$: Observable<State>,
export function useObservable<State = any>(
obs$: Observable<State>|null|undefined,
setState: (state: State) => any
) {
useEffect(() => {
if (!obs$) {
return;
}
const sub = obs$.subscribe((state: State) => {

@@ -25,6 +28,13 @@ setState(state);

*/
export function useObservableState<State>(
obs$: Observable<State>,
initialState: State = null
): State {
export function useObservableState<State = any>(
obs$: Observable<State>|null|undefined,
initialState: State
): State;
export function useObservableState<State = any>(
obs$: Observable<State>|null|undefined
): State | null;
export function useObservableState<State = any>(
obs$: Observable<State>|null|undefined,
initialState: State | null = null
): State | null {
const [state, setState] = useState(initialState);

@@ -38,4 +48,4 @@ useObservable(obs$, setState);

*/
export function useSubject<State>(sub$: BehaviorSubject<State>) {
return useObservableState(sub$, sub$.value);
export function useSubject<State = any>(sub$: BehaviorSubject<State>|null|undefined) {
return useObservableState(sub$, sub$?.value ?? null);
}

@@ -0,29 +1,29 @@

import { useContext, useEffect, useState } from "react";
import {
DependencyList,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState
} from 'react';
import {
CheckRequestResult, checkRequestState,
CheckRequestResult,
checkRequestState,
CheckRequestStateFn,
IRequestState,
IRequestStoreOptions,
RequestStore,
} from '@proscom/prostore';
import { useConnectStore } from './useConnectStore';
import { useContextStore } from './ProstoreContext';
import { ProstoreSsrContext } from './ProstoreSsrContext';
GetRequestStoreData,
GetRequestStoreOptions,
GetRequestStoreState,
GetRequestStoreVars,
RequestStore
} from "@proscom/prostore";
import { useLatestCallbackRef } from "@proscom/ui-react";
import { useConnectStore } from "./useConnectStore";
import { useContextStore } from "./ProstoreContext";
import { ProstoreSsrContext } from "./ProstoreSsrContext";
export interface UseRequestStoreResult<Vars, Data, Options> {
export interface UseRequestStoreResult<Store extends RequestStore> {
check: CheckRequestResult;
state: IRequestState<Vars, Data>;
load: (options?: Options) => Promise<IRequestState<Vars, Data>>;
store: RequestStore<Vars, Data, Options>;
state: GetRequestStoreState<Store>;
load: (
options?: GetRequestStoreOptions<Store>
) => Promise<
GetRequestStoreState<Store>
>;
store: Store;
}
export interface UseRequestOptions<Vars, Data> {
export interface UseRequestOptions<Vars = any, Data = any> {
checkRequest?: CheckRequestStateFn<Vars, Data>;

@@ -33,3 +33,3 @@ }

/**
* Attached component to the provided store and requests data based on the variables and options
* Attaches component to the provided store and requests data based on the variables and options
*

@@ -43,19 +43,18 @@ * @param storeOrName - RequestStore to subscribe to, or its name for it to be injected from the context

*/
export function useRequestStore<
Vars,
Data,
Options extends IRequestStoreOptions<Vars, Data>
>(
storeOrName: string | RequestStore<Vars, Data, Options>,
variables: Vars,
options: Options = undefined,
hookOptions: UseRequestOptions<Vars, Data> = {}
): UseRequestStoreResult<Vars, Data, Options> {
export function useRequestStore<Store extends RequestStore>(
storeOrName: string | Store,
variables: GetRequestStoreVars<Store> | undefined = undefined,
options: GetRequestStoreOptions<Store> | undefined = undefined,
hookOptions: UseRequestOptions<
GetRequestStoreVars<Store>,
GetRequestStoreData<Store>
> = {}
): UseRequestStoreResult<Store> {
const checkRequest = hookOptions.checkRequest || checkRequestState;
// Inject store from context
const store = useContextStore<RequestStore<Vars, Data, Options>>(storeOrName);
const store = useContextStore<Store>(storeOrName);
// Local copy of store state
const [state, setState] = useState(store.state);
const [state, setState] = useState<GetRequestStoreState<Store>>(store.state);

@@ -69,11 +68,7 @@ // Subscribe to store changes

// Memoized callback to request data
const funcsRef = useRef<{
loadData?: UseRequestStoreResult<Vars, Data, Options>['load'];
}>({});
funcsRef.current.loadData = (newOptions = undefined) => {
return store.loadData(variables, newOptions || options);
};
const loadData = useCallback((newOptions = undefined) => {
return funcsRef.current.loadData(newOptions);
}, []);
const loadData = useLatestCallbackRef(
(newOptions: GetRequestStoreOptions<Store> | undefined = undefined) => {
return store.loadData(variables, newOptions || options);
}
);

@@ -101,21 +96,1 @@ // Request the data if it is should be requested

}
/**
* The same as useRequestStore, but it uses variableCreator which is supplied to useMemo and
* can be used to memoize query variables. This may be used when the default behavior of deeply
* comparing variables is not preferable (i.e., it is not fast enough, or variables are not simple objects)
*
* @returns {{load, check, state}} - Current request state
*/
export function useRequestStoreVars<
Vars,
Data,
Options extends IRequestStoreOptions<Vars, Data>
>(
storeOrName: string | RequestStore<Vars, Data, Options>,
variableCreator: () => Vars,
args: DependencyList
) {
const variables = useMemo(variableCreator, args);
return useRequestStore(storeOrName, variables);
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc