nycticorax
TypeScript icon, indicating that this package has built-in type declarations

4.1.4 • Public • Published

nycticorax

Build Status codecov

State container for JavaScript application, and React

https://fratercula.github.io/nycticorax/

Install

$ npm i nycticorax

Usage

For React, it is simple use, not Provider, reducer, action, only connect. useStore for Hooks

import React, { Component } from 'react'
import Nycticorax from 'nycticorax'

type Store = { name: string, age: number }

const nycticorax = new Nycticorax<Store>()

const {
  createStore,
  dispatch,
  connect,
  useStore,
  emit,
} = nycticorax

createStore({ age: 0, name: 'abc' })

class A0 extends Component<Store> {
  onClick = () => {
    emit({ 'name': 'xyz' })
  }

  render() {
    const { name } = this.props
    return (
      <div>
        <p>{name}</p>
        <button onClick={this.onClick}>set</button>
      </div>
    )
  }
}

const A = connect('name')(A0)

// Hooks
function B() {
  const { name } = useStore('name')

  return (
    <div>
      <p>{name}</p>
      <button onClick={() => emit({ name: 'jkl' })}>name</button>
    </div>
  )
}

export default () => (
  <>
    <A />
    <B />
  </>
)

API

width typescript

import Nycticorax, { Dispatch as DP } from 'nycticorax'

type Store = { name: string }

const nycticorax = new Nycticorax<Store>()

const {
  createStore,
  getStore,
  dispatch,
  subscribe,
  connect,
  useStore,
  emit,
} = nycticorax

type Dispatch = DP<Store>

width javascript

import Nycticorax from 'nycticorax'

const nycticorax = new Nycticorax()

const {
  createStore,
  getStore,
  dispatch,
  subscribe,
  connect,
  useStore,
  emit,
} = nycticorax

without React

// not `connect` and `useStore`
import Nycticorax, { Dispatch as DP } from 'nycticorax/core'

type Store = { name: string }

const nycticorax = new Nycticorax<Store>()

const {
  createStore,
  getStore,
  dispatch,
  subscribe,
  emit,
} = nycticorax

type Dispatch = DP<Store>

createStore

create store

type createStore = (state: T) => void

createStore({ name: 'nycticorax', [Symbol('key')]: 'symbol' })

getStore

get store

type getStore<T> = (key? keyof T) => T | T[keyof T]

const store = getStore() // { name: 'nycticorax' }
const name = getStore('name')

emit

update store

type emit = (next: Partial<T>, params: Record<string, any>) => void;

// update store key `name`, value is `xyz`
emit({ name: 'xyz' })

// multiple key
emit({ name: 'xyz', another: 1 })

by default, emit action will be merged

emit({ a: 1, b: 2 })
emit({ b: 1 })

// will be merged as
emit({ a: 1, b: 1 })

set emit to sync

createStore({ a: 1 })
emit({ a: 2 }, true)
console.log(getStore('a')) // { a: 2 }

dispatch

const asyncDispatch: Dispatch = async ({ emit, getStore }, params) => {
  console.log(params)
  return new Promise((resolve) => {
    // get current store
    const { name } = getStore()

    // update name
    emit({ name: 'a' })

    setTimeout(() => {
      emit({ name: 'b' })

      // resolve
      resolve(name)
    }, 1000)
  })
}
dispatch(asyncDispatch, { a: 'b' }).then((name) => {
  console.log(name)
}

sync emit

// async
createStore({ a: 1 })
emit({ a: 2 })
console.log(getStore('a')) // { a: 1 }
setTimeout(() => console.log(getStore('a'))) // { a: 2 }

function asyncDispatch({ emit, getStore }) {
  return new Promise((resolve) => {
    // update name
    emit({ name: 'a' }) // sync dispatch
    console.log(getStore('name')) // a

    setTimeout(() => {
      emit({ name: 'b' }) // sync dispatch
      console.log(getStore('name')) // b

      // resolve
      resolve(name)
    }, 1000)
  })
}

subscribe

watch key change

type Listener = (newValue: unknown, oldValue: unknown) => void;
type KeyWithListener<T> = Partial<Record<keyof T, Listener>>;
type subscribe: (listener: KeyWithListener<T>) => () => void;

const unsubscribe = subscribe({
  time(newValue, oldValue) {
    console.log(newValue, oldValue)
  },
})
unsubscribe() // unsubscribe

onChange

watch store change

type ChangeValue<T> = Record<keyof T, [newValue: unknown, oldValue: unknown]>;
type OnChange<T> = (value: ChangeValue<T>) => void;

const nycticorax = new Nycticorax<Store>()

nycticorax.onChange = (v) => {
  console.log(v, 'onChange')
}

connect

for React only

class component cannot props symbol key, use getStore get symbol key`s value https://github.com/facebook/react/issues/7552

type connect = (keys: (keyof T)[]) => (React.ComponentType) => React.ComponentType

const symbolKey = Symbol('key')

class A extends Component<Store> {
  render() {
    const { name, another } = this.props
    const store = getStore()
    return (
      <div>
        <h2>Component A</h2>
        <p>name: {name}</p>
        <p>{store[symbolKey]}</p>
      </div>
    )
  }
}

export default connect('name', symbolKey)(A)

useStore

for React only

type useStore = ((keyof T)[]) => T

function B() {
  const { name } = useStore('name')
  return (
    <>
      <p>{name}</p>
      <button onClick={() => emit({ name: 'jkl' })}>x</button>
    </>
  )
}

License

MIT

Readme

Keywords

Package Sidebar

Install

npm i nycticorax

Weekly Downloads

3

Version

4.1.4

License

MIT

Unpacked Size

49.3 kB

Total Files

12

Last publish

Collaborators

  • loeify