frejs / fre

:ghost: Tiny Concurrent UI library with Fiber.

Home Page:https://fre.deno.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

useContext or similar global shared state system

wcastand opened this issue · comments

i've seen a few mention on it in the different Pr/issues but can't find anything about it in the current fre package.
Is it still something that is planned?
A Pr was also talking about a fre/compat for context. Is this a future plan or already there(couldn't find it)?

Because of the upgrade of new version fre2, this work was not performed, but this is what we will do in the future.

Shared state may be easy with hooks API, for example:

export const createContext = defaultValue => {
  const context = {
    value: defaultValue,
    subs: new Set(),
    Provider: function Provider({ value, children }) {
      useLayout(() => {
        context.subs.forEach(fn => fn(value))
        context.value = value
      })
      return children
    }
  }
  return context
}

export const useContext = (context, selector) => {
  const subs = context.subs
  const [, forceUpdate] = useReducer(c => c + 1, 0)
  const selected = selector ? selector(context.value) : context.value
  const ref = useRef(null)
  useEffect(() => {
    ref.current = selected
  })
  useEffect(() => {
    const fn = nextValue => {
      if (ref.current === selector(nextValue)) return
      forceUpdate()
    }
    subs.add(fn)
    return () => subs.delete(fn)
  }, [subs])
  return selected
}

const Context = createContext({ count1: 0, count2: 1 })

function App(){
  const context = useContext(Context, ctx => ctx.count1) // selector
...
}

After fre2 is finally released, we can add some api and compat packages, it will be soon.

Keep this issue open until a better implemention land.

It would be great if it would be possible to use somethings like Atoms from Recoil.

@Rados51 To be honest, this is difficult, because recoil depends on useContext and useMutableSource, and fre does not have these two APIs yet.

@yisar Thanks for a quick response. I've just came across your library and it seems like a perfect solution for project I am working with and it doesn't require whole complexity of React. What would be the best way to pass states between child/parent — props? Thank You and wish you best luck.

In fact, if props are passed across components, useContext is the most appropriate, because it does not produce tearings.

If you like atom, you can try jotai, but it is also based on context. I will implement context in fre in the future.

Check this out:

https://github.com/DaemonAlchemist/unstateless

Compared with context, this seems so much more natural in the context of hooks.

I wonder if something like this wouldn't also be simpler, easier to implement, and possibly smaller, than contexts?

If we had e.g. useSharedState and useSharedReducer, that seems like an shoe-in for a framework with pure hooks, and should pretty much cover all the bases?

(I'm not 100% sure about the naming - these functions aren't technically hooks, but functions that create hooks... so maybe names like createSharedState and createSharedReducer is better?)

I suppose contexts might also be worth supporting - if nothing else, then just for compatibility with React... but if it's actually simpler and easier to implement a more natural API than that...

@mindplay-dk I don't want to use pub-sub in the core code of fre (just like preact).
If I have to, I prefer to set shoudComponentUpdate for all components, and then use pub-sub similar technologies