atellmer / dark

The lightweight and powerful UI rendering engine without dependencies and written in TypeScript💫 (Browser, Node.js, Android, iOS, Windows, Linux, macOS)
MIT License
41 stars 1 forks source link

Adds a new Context API #70

Closed atellmer closed 4 months ago

atellmer commented 4 months ago

Removed unnecessary Context.Provider and Context.Consumer. Now the context itself is a provider.

It was like this

<SomeContext.Provider value={value}>
  ...
</SomeContext.Provider>

then it became like that

<SomeContext value={value}>
 ...
</SomeContext>
atellmer commented 4 months ago

I will also try to add the ability not to update the entire subtree using refs.

einar-hjortdal commented 4 months ago

This will affect my TranslationsProvider, will have to update it. Essentially the .Consumer was removed and the only way to consume context is by using useContext? That's good.

atellmer commented 4 months ago

Yes, I was going to mention you. The simpler the API, the better.

atellmer commented 4 months ago

I realized that using context and atoms completely solves the problem of updating the entire subtree, so it probably doesn't make sense to add another way to do it.

const value$ = useAtom(0);

<SomeContext value={value$}>
 ...
</SomeContext>
const useValue = () => {
  const atom$ = useContext(SomeContext);

  return atom$.val() // subscribes
}

value$.set(10500) - updates only consumers

Perhaps this approach can be used instead tons of state managers: context for dependency injections, atoms - for micro updates.

einar-hjortdal commented 4 months ago

Perhaps this approach can be used instead tons of state managers: context for dependency injections, atoms - for micro updates.

I don't know if you remember react v15's "unstable" getChildrenContext API. With that one does dependency injection, then wrap every component with an HOC that consumed context by adding an event listener (like an atom) and passing the changes in values as props. As usual when consumers update, all their children also update.

I don't think it would be that different, unless atoms were able to update consumers without propagating updates to children (Solid-like updates).

atellmer commented 4 months ago

able to update consumers without propagating updates to children

Since we are using a render approach, this is normal default behavior. However, if necessary, you can achieve a point update by dividing the component into smaller components, or using children memoization.

einar-hjortdal commented 4 months ago

I think there is a regression caused by the latest changes, going from 1.3.0 to 1.4.0, that affects the behavior my application. In particular it seems to affect the behavior of my component that relies on animate's useTransition

I am trying to investigate, but it is proving rather difficult. For whatever reason, checking out an older commit of my app breaks the app entirely, so I can't compare with previous versions.

Something seems to be affecting the mounting and unmounting of components when the transition starts and when the transition is over. I can't figure out what it is though

This makes me sad :cry: it was working so good earlier today

atellmer commented 4 months ago

All tests passed successfully, the animations did not change. I need more detailed information about what is not working for you.

einar-hjortdal commented 4 months ago

I have updated my repository, the problem manifests there too. It looks like both at the beginning and end of the transition in the PageTransition component, Animated and the children are unmounted and then mounted again. This causes my intersection-observer events to retrigger and the leaving page to scroll to the top during the transition. This did not happen on 1.3.0.

My app is wrapped in TranslationsProvider which I have updated for 1.4.0. I am trying to understand if the Context changes are causing something to that

Update: no it does not seem like Context is causing unmounts/mounts. The problem seems scoped to PageTransition. All I know for sure is: I did not change PageTransition today, and this issue wasn't there on 1.3.0 :confused:

Transitioning from /contact to /home results in home being mounted, then unmounted and mounted again at the end of the transition.

const Home = component(() => {
  const { t } = useTranslation()
  useEffect(() => {
    console.log('mounted home')
    return () => console.log('unmounted home')
  }, [])

image

atellmer commented 4 months ago

Ok, plase stay on 1.3.0. I will check it later. I found one bug with node unmounting, maybe this is it.

atellmer commented 4 months ago

I reproduced this bug in stackblitz:

einar-hjortdal commented 4 months ago

Thank you, I am so glad I am not insane :heart:

atellmer commented 4 months ago

fixed in 1.4.1 with git bisect 😊

einar-hjortdal commented 4 months ago

It seems like using useContext outside of a provider causes Dark to throw an getCursorFiber is undefined error. I will provide repro if needed

I was wrong, useContext works correctly, the error was caused by my development environment and Bun being unable to import the symbolic-linked library correctly, (issue 10223).