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.
- Host: GitHub
- URL: https://github.com/1111mp/simple-store
- Owner: 1111mp
- License: mit
- Created: 2023-08-26T04:02:41.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2023-08-30T04:45:17.000Z (almost 2 years ago)
- Last Synced: 2024-10-30T06:56:44.837Z (7 months ago)
- Topics: react, react-hooks, reactjs, simple-store, state-management
- Language: TypeScript
- Homepage: https://github.com/1111mp/simple-store
- Size: 124 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
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
[](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 somethingreturn {
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`.