1.0.62 • Published 9 months ago

reasy-state v1.0.62

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Build Status Build Size Version Downloads

Reast Easy State

Reast Easy State is simple state management for React

Reasy-state allows you to easily work with your state without creating selectors or worrying about re-renders, by having each object or array element have its own hook for getting the value, get/set functions and mutators. It is also possible save state to storage to initialize the state in the server side component

Installation

To install the latest stable version, run the following command:

npm install reasy-state

Usage example

Create a state

Create state and export necessary functions

The function names will be generated automatically, depending on your object. ( get*, set*, use* and reset)

// store.ts

import { createState } from "reasy-state";

const userStore = {
    id: 1,
    name: "User Name",
    settings: {
        notification: true,
    },
};

export const {
    getUserStoreId,
    useUserStoreName,
    useUserStoreSettingsNotification,
    setUserStoreSettingsNotification,
    reset,
} = createState({ userStore });

Use exported functions in your components

// user.tsx

import { getUserStoreId, useUserStoreName, reset } from "./store";

const UserComponent = () => {
    const userName = useUserStoreName();

    return (
        <div>
            <p onClick={() => console.log("User ID:", getUserStoreId())}>
                {userName}
            </p>
            <button onClick={reset}>Reset store</button>
        </div>
    );
};
// setting.tsx

import {
    setUserStoreSettingsNotification,
    useUserStoreSettingsNotification,
} from "./store";

const SettingsNotificationComponent = () => {
    const checked = useUserStoreSettingsNotification();

    return (
        <input
            type="checkbox"
            checked={checked}
            onChange={() => setUserStoreSettingsNotification((prev) => !prev)}
        />
    );
};

Mutators

You can use mutators to export functions. You can also use closures and async functions inside mutators. Use a set or patch function that takes a new value, or a function that takes the old value as a parameter and returns a new value, to change the state of the current object in the state. set / patch will return you the new state of the object. Use a get function for async mutators, for get previous object value, or use second function argument

mutators: {
  [functionName]: ({set, patch, get}, previousValue) => ...
}
// store.ts
import { createState, CreateState } from "reasy-state";

type State = CreateState<{ value: number; mutators: { inc: void } }>;

export const { useValue, inc } = createState<State>({
    value: 1,
    mutators: {
        inc: ({ set }, { value }) => set({ value: value + 1 }),
    },
});
// page.tsx
import { useValue, inc } from "./store.ts";

export const Page = () => {
    const value = useValue();

    return (
        <>
            <div>value: {value}</div>
            <button onClick={() => inc()}>inc</button>
        </>
    );
};

Also, you can avoid specifying mutator types explicitly by using currying, and also use nested mutators

// store.ts
import { createState } from 'reasy-state';

type UserStore = {
  userStore: {
    id: number;
    data: {
      rating: number;
    };
  };
};

export const {
  userStoreDataClear,
  useUserStoreDataRating,
} = createState<UserStore>()({
  userStore: {
    id: 1,
    data: {
      rating: 1,
      mutators: {
        clear: ({ set }) => set({ rating: 0 }).rating, // return 0
      },
    },
  },
});

Async mutators

// store.ts
import { createState, CreateState } from "reasy-state";

type State = {
    value: number;
    mutators: {
        add: (value: number) => Promise<number>;
    };
};

const { useValue, add } = createState<State>()({
    value: 1,
    mutators: {
        add:
            ({ set, get }) =>
            async (addValue) => {
                await new Promise((f) => setTimeout(f, 1000));
                return set({ value: get().value + addValue }).value;
            },
    },
});
// page.tsx
import { useValue, inc } from "./store.ts";

export const Page = () => {
    const value = useValue();
    const onClick = () =>
          add(1).then((value) => console.log("new value = ", value));

    return (
        <>
            <div>value: {value}</div>
            <button onClick={onClick}>add async</button>
        </>
    );
};

Undefined params

You can use functions for undefined parameters using the $ sign

// store.ts
type UserStore = {
    id: number,
    data?: {
        rating: number,
    },
};
const userStore: CreateState<UserStore> = {
    id: 1,
};

export const { useUserStore$data$rating } = createState({ userStore });

Arrays

You can use arrays parameters functions using the $ sign

For array element set, get and use functions, you can use a filter to specify which elements you need to get or change

get`[...functionName]`(filterFunction?);
use`[...functionName]`(filterFunction?);
set`[...functionName]`(filterFunction, newValue);
// store.ts

type UserStore = {
    id: number,
    subscribers: {
        id: number,
        rating: number,
    }[],
};

const userStore: CreateState<UserStore> = {
    id: 1,
    subscribers: [
        { id: 2, rating: 10 },
        { id: 3, rating: 12 },
    ],
};

export const {
    useUserStoreSubscribers$rating,
    setUserStoreSubscribers$rating,
} = createState({ userStore });
export const Ratings = () => {
    const ratings = useUserStoreSubscribers$rating(({ rating }) => rating);

    const add = () =>
        setUserStoreSubscribers$rating(
            ({ id }) => id === 2,
            (prev) => prev + 1,
        );

    const clear = () => setUserStoreSubscribers$rating(() => true, 0);

    return (
        <div>
            <p>Positive ratings = {ratings.join(",")}</p>
            <button onClick={add}>Add rating for id 2</button>
            <button onClick={clear}>Clear rating for all</button>
        </div>
    );
};

Usage in ssr components :warning: (experemental)

You can initialize your state or part of it in a server component like this:

//store.ts
'use client';

import { createState } from 'reasy-state';

type Store = {
    user: {
        id: number;
        name: string;
    };
};

export const { use$user$id, get$user$id, ssr: { SSR$user } } = createState<Store>()();
//page.tsx
"use server";

export default async function ServerPage() {
    const data = await getUser("username"); // data = {id, name}
    return (
        <>
            <SSR$user value={data} />
            <ClientPage />
        </>
    );
}
"use client";

import { get$user$id, use$user$id } from "./store";

export const ClientPage = () => {
    const id = use$user$id();
    return <p>User id = {id}</p>;
};

Storage

You can save the state in the store( localStorage (default), sessionStorage ) To do this, specify a unique key and configure saving if necessary

    const { ... } = createState(
        { store: { value: "value" } },
        { key: "storage_state_1", storage: true }
    );

:warning: If SSR is used together with storage, the latter will be initialized only after the component is rendered to avoid hydration warning. To do this, specify the ssr: true parameter.

    const { ... } = createState(
        { store: { value: "value" } },
        { key: "storage_state_2", storage: true, ssr: true }
    );

If necessary, you can mutate the data on read and write like this (This can be useful when using momentjs for example):

    const store = { id: 1, date: moment() };

    const { ... } = createState(
        { store },
        {
            key: "session_storage_date_1",
            storage: {
                type: sessionStorage,
                mutators: {
                    store: {
                        date: (mutate) =>
                            mutate({
                                put: (prev) => prev.toISOString(),
                                get: (prev) => moment(prev),
                            }),
                    },
                },
            },
        },
    );
1.0.62

9 months ago

1.0.61

9 months ago

1.0.60

9 months ago

1.0.59

9 months ago

1.0.58

9 months ago

1.0.51

9 months ago

1.0.55

9 months ago

1.0.54

9 months ago

1.0.53

9 months ago

1.0.52

9 months ago

1.0.57

9 months ago

1.0.56

9 months ago

1.0.50

9 months ago

1.0.49

9 months ago

1.0.26

10 months ago

1.0.25

10 months ago

1.0.24

10 months ago

1.0.23

10 months ago

1.0.29

10 months ago

1.0.28

10 months ago

1.0.27

10 months ago

1.0.33

10 months ago

1.0.32

10 months ago

1.0.31

10 months ago

1.0.30

10 months ago

1.0.37

10 months ago

1.0.36

10 months ago

1.0.35

10 months ago

1.0.34

10 months ago

1.0.39

10 months ago

1.0.38

10 months ago

1.0.40

10 months ago

1.0.44

10 months ago

1.0.43

10 months ago

1.0.42

10 months ago

1.0.41

10 months ago

1.0.48

10 months ago

1.0.47

10 months ago

1.0.46

10 months ago

1.0.45

10 months ago

1.0.21

1 year ago

1.0.20

1 year ago

1.0.19

1 year ago

1.0.18

1 year ago

1.0.17

1 year ago

1.0.16

1 year ago

1.0.15

1 year ago

1.0.14

1 year ago

1.0.13

1 year ago

1.0.12

1 year ago

1.0.11

1 year ago

1.0.10

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6-a

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago