Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Context #107

Closed
JacopoPatroclo opened this issue Jan 22, 2024 · 4 comments
Closed

Support for Context #107

JacopoPatroclo opened this issue Jan 22, 2024 · 4 comments
Assignees
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@JacopoPatroclo
Copy link

Hi! Thanks for this library and the work you have put into it! Given your knowledge about this project it would be possible to create a "react like" context implementation?

I would love to make a PR.
I already kind of implemented something like that in this fastify plugin https://github.com/JacopoPatroclo/cose/blob/main/packages/fastify-jsx/src/lib/context.tsx but it's not convincing. It requires to handle children as a function to postpone their execution in order to give them access to the context. I'm sure there is a better way to do it. What are your thoughts @arthurfiorette ?

@arthurfiorette
Copy link
Member

Related: #31

@arthurfiorette arthurfiorette self-assigned this Jan 22, 2024
@arthurfiorette arthurfiorette added documentation Improvements or additions to documentation enhancement New feature or request labels Jan 22, 2024
@arthurfiorette arthurfiorette moved this to 🔖 Ready in Kita development Jan 22, 2024
@arthurfiorette
Copy link
Member

I'm contemplating whether a React-like context should be implemented in a library that shares a similar syntax with React (JSX) but is not a library itself; instead, it functions as a sophisticated template engine:

  1. A per-request ID MUST be used in every piece of code that accesses the state. This is crucial because it can be employed with async components, and a web server WILL have more than one request (and promise chain) simultaneously.

  2. The only way to maintain data consistency across concurrent renders without attaching a request locator, such as an rid used in the current Suspense implementation, is by using ALS. However, this approach is slow to the point that another framework had to revert its implementation of it due to performance problems.

  3. In a sophisticated template engine like @kitajs/html, no mutation can be performed. useEffects or setStates cannot work with raw strings and require a reactive framework behind them, which is not the case here. Kitajs/html transforms JSX into strings and nothing more.

  4. It is also not technically possible because JSX is evaluated from the deepest child to the highest parent, in this specific order. This evaluation order does not align with <Context.Provider> and useContext(Context) patterns.

  5. This brings us to the point that Context could only help avoid prop drilling, which is generally considered undesirable. However, due to the reasons mentioned above, at least one property (request.id) should be drilled mandatorily. If at least one property needs to be drilled, why not allow the user to drill their own context object? This would be faster because no hooks to the request lifecycle would be necessary.

  6. In the end, property drilling is not inherently bad in this template engine, as state won't travel across components, and only "maintainability" could be slightly impacted. Besides, JSX is predominantly used with TypeScript, and type drilling can be employed to avoid out-of-sync property types among all children.

This is my current idea for adding a context-like implementation into kitajs/html. I would love to hear your opinion on this.

@JacopoPatroclo
Copy link
Author

JacopoPatroclo commented Jan 22, 2024

First of all, I'm sorry that I have reopened this discussion again. I'll go by points:

  1. I did some tests and you are 100% correct.
  2. I'm a devex > performance kind of guy but I agree with keeping the core as fast as possible. Maybe it could be an opt-in thing with big disclaimers on performance tradeoffs.
  3. I understand that my point is to avoid prop drilling (for example passing the Fastify instance around to all the components).
  4. That could be resolved by accepting as a child of the context provider a function.
  5. I think you got the crux of the issue.

So I'm going to scratch the context idea. An implementation that requires passing the request ID to consume the correct context is as bad as prop drilling the context.
@arthurfiorette, If you accept, I will add a section on the readme on "why context is not a thing", it could be useful if someone like me ends up using this project facing the same dilemma.

@arthurfiorette
Copy link
Member

Awesome! Happy to see what you will achieve!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
Status: Done
Development

No branches or pull requests

2 participants