/resynced

An experimental hook that lets you have multiple components using multiple synced states using no context provider

Primary LanguageTypeScriptMIT LicenseMIT

Resynced (experimental)

❤️ Motivation

This is an experimental hook that lets you have multiple components using multiple synced states using no context provider.

And also provide a way of using that synced state with Redux!

This package requires the Hooks API available only in React 16.7.0-alpha.0 or later.

💻 Example

🔧 Install

$ yarn add resynced

🚀 How to Use

import { createSynced } from 'resynced'

const initialState = "John"
const [useSyncedState] = createSynced(initialState)

const UsingSharedState = () => {
  const [name, setName] = useSyncedState()

  return (
    <div>
      <h1>My name is {name}</h1>
      <button onClick={() => setName("Jorge")}>Change Name</button>
    </div>
  )
}

Using with Redux

Let's first setup our synced redux store (you must have redux installed in your project)

import { createSyncedRedux } from "resynced"
import { createStore } from "redux"

const initialState = {
  authenticated: false
}

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "LOGIN":
      return { ...state, authenticated: true }
    case "LOGOUT":
      return { ...state, authenticated: false }
    default:
      return state
  }
}

const authStore = createStore(reducer)
const [useSyncedAuth] = createSyncedRedux(authStore)

export default useSyncedAuth

Now we can use that synced redux in any component without the need of adding a Context Provider anywhere.

import React from 'react'
import useAuth from './authStore'

const ComponentUsingAuth = React.memo(() => {
  // This component will only update when the 'authenticated'
  // property is updated
  const [{ authenticated }, dispatch] = useAuth(["authenticated"])

  return (
    <div>
      <h1>Authenticated? {authenticated ? "Yes" : "No"}</h1>
      <button onClick={() => dispatch({ type: "LOGIN" })}>Login</button>
      <button onClick={() => dispatch({ type: "LOGOUT" })}>Logout</button>
    </div>
  )
})  

export ComponentUsingAuth

You can check this working example here: Resynced With Redux

Conditional updates

Using a list of properties

The component local state will only be synced if any of the given properties of the state object changes (only works with object states).

import { createSynced }  from 'resynced'

const initialState = {
  name: "John"
}
const [useSyncedState] = createSynced(initialState)

const UsingSharedState = () => {
  const [state, setState] = useSyncedState(["name"])

  return (
    <div>
      <h1>My name is {name}</h1>
      <button onClick={() => setState({ name: "Jorge" })}>Change Name</button>
    </div>
  )
}

Using functions

The component local state will only be synced if the return of the given function is true.

import { createSynced } from 'resynced'

const [useSyncedState] = createSynced("John")

const UsingSharedState = () => {
  const [name, setName] = useSyncedState((newState, prevState) => {
    return newState !== "Foo"
  })

  return (
    <div>
      <h1>My name is {name}</h1>
      <button onClick={() => setName("Jorge")}>Change Name</button>
    </div>
  )
}