npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

sangte

v0.1.26

Published

Sangte is a fancy React state management library.

Downloads

21

Readme

sangte

English | 한국어

Sangte is a state management library for React. This library is inspired by Redux Toolkit and Recoil.

Sangte means "state" in Korean.

Installation

To install the library, run the following command:

npm install sangte

Or if you're using yarn:

yarn add sangte

Why sangte?

  • Less boilerplate
  • Rerender only when the state you're using is updated
  • Easy to use
  • Allows multiple providers
  • TypeScript support

Usage

First create a state

To create a state you need to use the sangte function. A state of sangte should have a default value, and actions to update the state. Actions are optional.

Sangte uses immer internally to update the state. So you can mutate the state directly while keeping the immutability.

import { sangte } from 'sangte'

const counterState = sangte(0)
const textState = sangte('text')
const userState = sangte({ id: 1, name: 'John', email: '[email protected]' }, (prev) => ({
  setName(name: string) {
    prev.name = name
  },
  setEmail(email: string) {
    return {
      ...prev,
      email,
    }
  },
}))

interface Todo {
  id: number
  text: string
  done: boolean
}

const todosState = sangte<Todo[]>([], (prev) => ({
  add(todo: Todo) {
    return prev.push(todo)
  },
  remove(id: number) {
    return prev.filter((todo) => todo.id !== id)
  },
  toggle(id: number) {
    const todo = prev.find((todo) => todo.id === id)
    todo.done = !todo.done
  },
}))

Use the state or actions from your components

The library provides hooks to utilize the state or actions from your components.

useSangte

useSangte works like useState from React, but it works globally. It returns the state and a setter function to update the state.

import { sangte, useSangte } from 'sangte'

const counterState = sangte(0)

function Counter() {
  const [counter, setCounter] = useSangte(counterState)
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={() => setCounter((prev) => prev + 1)}>Increment</button>
      <button onClick={() => setCounter(0)}>Reset</button>
    </div>
  )
}

export default Counter

useSangteValue

If you only need the value of the state, you can use useSangteValue.

import { useSangteValue } from 'sangte'

const counterState = sangte(0)

function CounterValue() {
  const counter = useSangteValue(counterState)
  return <h1>{counter}</h1>
}

If you want to select a part of the state, you can pass selector function as second argument. If you select multiple fields, the component will rerender after shallow comparison. You can override the comparison function by passing a custom equality function to third argument.

import { sangte, useSangteValue } from 'sangte'

const userState = sangte({ id: 1, name: 'John', email: '[email protected]' })

function User() {
  const { name, email } = useSangteValue(userState, (state) => ({
    name: state.name,
    email: state.email,
  }))
  return (
    <div>
      <h1>{name}</h1>
      <h2>{email}</h2>
    </div>
  )
}

If you want to use a memoized selector that is prcessed only when its dependencies update, you can create a read-only Sangte as below.

import { sangte } from 'sangte'
const todosState = sangte([
  { id: 1, text: 'Basic usage', done: true },
  { id: 21, text: 'Ready-only sangte', done: false },
])
const undoneTodosValue = sangte((get) => get(todosState).filter((todo) => !todo.done))
function UndoneTodos() {
  const undoneTodos = useSangteValue(undoneTodosValue)

  return <div>{undoneTodos.length} todos undone.</div>
}

useSetSangte

If you only need the updater function of the state, you can use useSetSangte.

import { sangte, useSetSangte } from 'sangte'

const counterState = sangte(0)

function CounterButtons() {
  const setCounter = useSetSangte(counterState)
  return (
    <div>
      <button onClick={() => setCounter((prev) => prev + 1)}>Increment</button>
    </div>
  )
}

useSangteActions

If you have defined actions for the state, you can use useSangteActions to get the actions.

import { sangte, useSangteActions } from 'sangte'

const counterState = sangte(0, (prev) => ({
  increase() {
    return prev + 1
  },
  decreaseBy(amount: number) {
    return prev - amount
  },
}))

function CounterButtons() {
  const { increase, decreaseBy } = useSangteActions(counterState)
  return (
    <div>
      <button onClick={increase}>Increase</button>
      <button onClick={() => decreaseBy(10)}>Decrease</button>
    </div>
  )
}

useResetSangte

If you want to reset the state to its default value, you can use useResetSangte.

import { sangte, useResetSangte } from 'sangte'

const counterState = sangte(0)

function Counter() {
  const [counter, setCounter] = useSangte(counterState)
  const resetCounter = useResetSangte(counterState)
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={() => setCounter((prev) => prev + 1)}>Increment</button>
      <button onClick={resetCounter}>Reset</button>
    </div>
  )
}

useResetAllSangte

If you want to reset all the states to their default values, you can use useResetAllSangte. This hook also resets sangte inside the nested providers.

import { sangte, useResetAllSangte } from 'sangte'

const counterState = sangte(0)
const textState = sangte('text')

function Counter() {
  const [counter, setCounter] = useSangte(counterState)
  const [text, setText] = useSangte(textState)
  const resetAll = useResetAllSangte()

  return (
    <div>
      <h1>
        {counter} | {text}
      </h1>
      <button onClick={() => setCounter((prev) => prev + 1)}>Increment</button>
      <button onClick={() => setText('Hello World'}>Update Text</button>
      <button onClick={resetAll}>Reset</button>
    </div>
  )
}

If you want to reset the states globally (including all parent providers), you can pass true as first argument.

import { sangte, useResetAllSangte } from 'sangte'

function RestAll() {
  const resetAll = useResetAllSangte()
  return <button onClick={() => resetAll(true)}>Reset All</button>
}

useSangteCallback

If you want to use the state in a callback but you do not want to rerender the component as the state changes, you can use useSangteCallback.

import { sangte, useSangteCallback } from 'sangte'

const valueState = sangte('hello world!')

function ConfirmButton() {
  // this component won't rerender even when valueState changes
  const confirm = useSangteCallback(({ get }) => {
    const value = get(valueState)
    console.log(value) // do something with value..
  }, [])

  return <button onClick={confirm}>Confirm</button>
}

You can also use the setter function or actions with useSangteCallback.

import { sangte, useSangteCallback } from 'sangte'

const counterState = sangte(0, (prev) => ({
  add(value: number) {
    return prev + value
  },
}))

function Counter() {
  // calls add action
  const add2 = useSangteCallback(({ actions }) => {
    const { add } = actions(counterState)
    add(2)
  }, [])

  // sets counterState to 10000
  const set10000 = useSangteCallback(({ set }) => {
    set(counterState, 10000)
  }, [])

  return (
    <div>
      <button onClick={add2}>add 2</button>
      <button onClick={logCount}>logCount</button>
      <button onClick={set10000}>set 10000</button>
    </div>
  )
}

Recipe

Using multiple providers

Inheriting state from parent provider

Server side rendering

Docs are still in progress. If you have any questions, please open an issue.