@watch-state/react
TypeScript icon, indicating that this package has built-in type declarations

2.0.0-alpha.1 • Public • Published
Watch-State logo by Mikhail Lysikov

  @watch-state/react

 

NPM downloads changelog license tests

State manager for React 18+ based on watch-state

stars watchers

Install

npm

npm i @watch-state/react

Usage

useWatch

You can observe only function components, by useWatch hook.

import { State } from 'watch-state'
import { useWatch } from '@watch-state/react'

const show = new State(false)
const toggleShow = () => show.value = !show.value

const AsideMenuButton = () => (
  <button
    onClick={toggleShow}
  />
)

const AsideMenu = () => {
  const isShow = useWatch(show)

  return isShow ? (
    <div>Aside Menu</div>
  ) : null
}

useWatcher

You can observe only function components, by useWatcher hook.

import { State } from 'watch-state'
import { useWatcher } from '@watch-state/react'

const show = new State(false)
const toggleShow = () => show.value = !show.value

const AsideMenuButton = () => (
  <button
    onClick={toggleShow}
  />
)

const AsideMenu = () => {
  const isShow = useWatcher(() => show.value)
  // here is the difference ^^^^^^^^^^^^^^^

  return isShow ? (
    <div>Aside Menu</div>
  ) : null
}

useNewState

useNewState helps to create a State inside react component.

import { Observable } from 'watch-state'
import { useWatch, useNewState } from '@watch-state/react'
import { useEffect } from "react";

interface ChildProps {
  value: Observable<string>
}

const Parent = () => {
  console.log('Parent creates State once');

  const state = useNewState(0)

  useEffect(() => {
    const t = setInterval(() => {
      state.value++
    }, 1000)
    
    return () => {
      clearInterval(t)
    }
  }, [])

  return (
    <Test value={state}/>
  )
}

const Test = ({ value }: ChildProps) => {
  console.log('Test renders once and provides value to Child', value);

  return (
    <Child value={value}/>
  )
}

const Child = ({ value }: ChildProps) => {
  console.log('Child renders on value canges', value);

  const currentValue = useWatch(value)

  return (
    <div>
      {currentValue}
    </div>
  )
}

useNewCache

useNewCache helps to create a Cache inside a component.

import { State } from 'watch-state'
import { useWatch, useNewCache } from '@watch-state/react'

const name = new State('Mike')
const surname = new State('Deight')

const Parent = () => {
  const fullName = useNewCache(() => `${name.value} ${surname.value[0]}.`)
  // renders once
  return <Child fullName={fullName} />
}

interface ChildProps {
  fullName: Observable<string>
}

const Child = ({ fullName }: ChildProps) => {
  const value = useWatch(fullName)
  // renders when fullName canges
  return <div>{value}</div>
}

useNewCache also helps to combine props and Observable inside a component.

import { State } from 'watch-state'
import { useWatch, useNewCache } from '@watch-state/react'

const name = new State('Mike')

interface ParentProps {
  surname: string
}

const Parent = ({ surname }: ParentProps) => {
  const fullName = useNewCache(() => `${name.value} ${surname[0]}.`, [surname])
  // renders when surname changes
  return <Child fullName={fullName} />
}

interface ChildProps {
  fullName: Observable<string>
}

const Child = ({ fullName }: ChildProps) => {
  const value = useWatch(fullName)
  // renders when fullName canges
  return <div>{value}</div>
}

You can use all features watch-state ecosystem.

Cache example:

import { State, Cache } from 'watch-state'
import { useWatch } from '@watch-state/react'

const name = new State('Mike')
const surname = new State('Deight')
const fullName = new Cache(() => `${name.value} ${surname.value[0]}.`)

const User = () => {
  const value = useWatch(fullName)

  return (
    <>{value}</>
  )
}

@watch-state/history-api example:

import { useWatch } from '@watch-state/react'
import { locationPath, historyPush } from '@watch-state/history-api'

const goTest = () => {
  historyPush('/test')
}

const User = () => {
  const path = useWatch(locationPath)

  return (
    <button onClick={goTest}>
      {path}
    </button>
  )
}

@watch-state/async example:

import { useWatch, useWatcher } from '@watch-state/react'
import Async from '@watch-state/async'

const api = new Async(
  () => fetch('/api/test')
    .then(r => r.json())
)

const User = () => {
  const value = useWatch(api)
  const loading = useWatcher(() => api.loading)
  const loaded = useWatcher(() => api.loaded)
  const error = useWatcher(() => api.error)
  
  if (error) {
    return <div>Error!</div>
  }
  
  if (!loaded) {
    return <div>Loading</div>
  }

  return (
    <div className={loading && 'loading'}>
      {value.some.fields}
    </div>
  )
}

Links

Issues

If you find a bug or have a suggestion, please file an issue on GitHub

issues

Package Sidebar

Install

npm i @watch-state/react

Weekly Downloads

1

Version

2.0.0-alpha.1

License

MIT

Unpacked Size

12.1 kB

Total Files

6

Last publish

Collaborators

  • deight