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

https://github.com/1111mp/simple-store

Manage your state in the easiest way for React.
https://github.com/1111mp/simple-store

react react-hooks reactjs simple-store state-management

Last synced: 2 months ago
JSON representation

Manage your state in the easiest way for React.

Awesome Lists containing this project

README

        

## simple-store

Manage your state in the easiest way for React.

## Installation

```shell
npm run install @the1111mp/simple-store
# Or
yarn add @the1111mp/simple-store
```

## Example

You can see the code: [simple-store-example](https://github.com/1111mp/simple-store/tree/main/example)

Or

[![Edit](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/simple-store-example-cfj25d)

## Quick Start

#### Basic usage

Create a `userStore` through the `createStore` method:

```typescript
// user.store.ts
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

// directly assign the initialized value
export const [userStore, resetStore] = createStore({
name: "Tom",
age: 18,
});

// Or

// Use a function to get the initialized value (sync)
export const [userStore, resetStore] = createStore(() => {
// you can do something

return {
name: "Tom",
age: 18,
};
});

// Or

// Use a function to get the initialized value (async)
// Remember this will triggers an update
export const [userStore, resetStore] = createStore(
{ name: "", age: 0 },
async () => {
// you can do something
const { name, age } = await fetch("/user");

return {
name,
age,
};
}
);

// App.tsx
import { userStore } from "user.store";

export const App: React.FC = () => {
const [{ name, age }, updateUserStore] = userStore();

return (


App:


name: {name}


age: {age}


{
updateUserStore((store) => {
return { name: "Jim", age: 16 };
});
}}
>
update


);
};
```

#### Custom hooks

```typescript
// user.store.ts
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

const [userStore] = createStore({
name: "Tom",
age: 18,
});

export function useUserStore() {
const [{ name, age }, updateUserStore] = userStore();

const updateName = (name: string) => {
updateUserStore((store) => ({ ...store, name }));
};

return {
name,
age,
updateName,
};
}

// App.tsx
import { useUserStore } from "user.store";

export const App: React.FC = () => {
const { name, age, updateName } = useUserStore();

return (


App:


name: {name}


age: {age}


{
updateName("Jim");
}}
>
update


);
};
```

> It is recommended to use custom hooks to split and manage your Store.

#### Performance optimization

With the `depsFn` function, you can control the `state` you want to subscribe to to avoid unwanted updates. This is similar to the `deps` parameter of React's `useMemo` or `useEffect`.

```typescript
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

const [userStore] = createStore({
name: "Tom",
age: 18,
});

export function useUserNameStore() {
// depsFn
const [{ name }, updateUserStore] = userStore((store) => [store.name]);

const updateName = (name: string) => {
updateUserStore((store) => ({ ...store, name }));
};

return {
name,
updateName,
};
}
```

#### How to use it in class components

> Cannot pass `userStore` directly to `withStore`.

```typescript
// user.store.ts
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

const [userStore] = createStore({
name: "Tom",
age: 18,
});

export function useUserStore() {
const [{ name, age }, updateUserStore] = userStore();

const updateName = (name: string) => {
updateUserStore((store) => ({ ...store, name }));
};

return {
name,
age,
updateName,
};
}

// App.tsx
import { Component } from "react";
import { withStore } from "@the1111mp/simple-store";
import { useUserStore } from "user.store";

type Props = ReturnType & {};

class App extends Component {
render(): React.ReactNode {
const { name, age, updateName } = this.props;

return (


App


name: {name}


age: {age}


{
updateName("Jim");
}}
>
update


);
}
}

export default withStore(useUserStore, (userStore) => ({
...userStore,
}))(App);
```

#### Dependencies between stores

Single store:

```typescript
// weather.store.ts
import { createStore } from "@the1111mp/simple-store";

export type WeatherStore = {
weather: string;
temperature: number;
};

export const [weatherStore] = createStore({
weather: "sunny",
temperature: 28,
});

export function useWeatherNameStore() {
const [{ weather }, updateStore] = weatherStore((store) => [store.weather]);

const updateWeather = (weather: string) => {
updateStore((store) => {
return {
...store,
weather,
};
});
};

return {
weather,
updateWeather,
};
}

export function useTempStore() {
const [{ temperature }, updateStore] = weatherStore((store) => [
store.temperature,
]);

const updateTemperature = (temperature: number) => {
updateStore((store) => {
return {
...store,
temperature,
};
});
};

return {
temperature,
updateTemperature,
};
}

export function useWeatherStore() {
const { weather, updateWeather } = useWeatherNameStore();
const { temperature, updateTemperature } = useTempStore();

return {
weather,
temperature,
updateWeather,
updateTemperature,
};
}

// Test.tsx
import { Component } from "react";
import { withStore } from "@the1111mp/simple-store";
import { useWeatherStore } from "./weather.store";

type Props = ReturnType & {};

class Test extends Component {
render(): React.ReactNode {
console.log("rerender from Test");
const { weather, temperature, updateWeather, updateTemperature } =
this.props;
return (


Test


weather: {weather}


temperature: {temperature} 摄氏度


{
updateWeather("hot");
}}
>
update weather



{
updateTemperature(30);
}}
>
update temperature


);
}
}

export default withStore(useWeatherStore, (weatherStore) => ({
...weatherStore,
}))(Test);
```

Multiple Stores:

```typescript
// user.store.ts
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

export const [userStore] = createStore({
name: "Tom",
age: 18,
});

export function useUsertore() {
// depsFn
const [{ name, age }, updateStore] = userStore();

const updateUserStore = (user: Partial) => {
updateStore((store) => ({ ...store, ...user }));
};

return {
name,
age,
updateUserStore,
};
}

// weather.store.ts
import { createStore } from "@the1111mp/simple-store";
import { useUserStore } from "./user.store";

export type WeatherStore = {
weather: string;
temperature: number;
};

export const [weatherStore] = createStore({
weather: "sunny",
temperature: 28,
});

export function useInfoStore() {
const { name, age, updateUserStore } = useUserStore();
const [{ weather, temperature }, updateWeatherStore] = weatherStore();

const updateWeatherStore = (weather: Partial) => {
updateStore((store) => {
return {
...store,
...weather,
};
});
};

return {
name,
age,
weather,
temperature,
updateUserStore
updateWeatherStore,
};
}
```

#### Read only

In some scenarios, we only want to read the current value of a model, without subscribing to its updates.

`useStore.store`:

```typescript
import { createStore } from "@the1111mp/simple-store";

type UseStore = { name: string; age: number };

export const [userStore] = createStore({
name: "Tom",
age: 18,
});

// will not subscribe to updates
export function useInfoStore() {
const { name, age } = userStore.store;

return {
name,
age,
};
}
```

## API

#### createStore

```typescript
type Store = Record;
type ResetStore = (notify?: boolean) => void;

export declare function createStore(
initial: T,
initialFn?: (store: T) => Promise
): [UseStore, ResetStore];
export declare function createStore(
initial: () => T,
initialFn?: (store: T) => Promise
): [UseStore, ResetStore];
```

Create a Store.

#### UseStore

```typescript
type UpdateStoreNormal = (store: T) => T;
type UpdateStoreWithPromise = (store: T) => Promise;
type UpdateStore = (
val: T | UpdateStoreNormal | UpdateStoreWithPromise
) => void;
type DepFn = (store: T) => unknown[];

type UseStore = {
(depsFn?: DepFn): [T, UpdateStore];
store?: T;
};
```

Call the return value of the createStore function.

#### resetStore

Reset your store data.

```typescript
type ResetStore = (notify?: boolean) => void;
```

The param of `notify` default is `true`, reset store data then notify to trigger once update.

#### withStore

```typescript
export declare function withStore(
useStore: UseStore,
mapModelToProps: MapModelToProps
): InferableComponentEnhancerWithProps;
export declare function withStore(
useStores: UseStore[],
mapModelToProps: MapModelToProps
): InferableComponentEnhancerWithProps;
```

Used to link `store` and `class components`, similar to `connect` of `react-redux`.