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

[🐞] attribute of the layout or parent component doesn't be reactive from the change of the context of the child components. #7070

Closed
genki opened this issue Nov 18, 2024 · 9 comments
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working

Comments

@genki
Copy link
Contributor

genki commented Nov 18, 2024

Which component is affected?

Qwik Runtime

Describe the bug

I am making a layout that changes its look depending on its child, but the attributes of the layout is not reactive when the context is updated in the child components.
Strangingly, the contents of the layout is correctly changed reactively according to the update of the context.

The expected behaviour is the attribute should be changed reactively when the context updated.

Reproduction

https://qwikdev-build-v2.qwik-8nx.pages.dev/playground/#f=7VbBCsIwDP2V0pPCELw4HOhl4MmfEB1exMLwoMz%2Bu2mSptlWZR68eeu2vCxJX5KnSLMqyxxpiiHTCtmaeMJtjCe20OdI1w96BimwPzygJ2kIb7BAR3dxbWVs25zs057bprnacANUT7Kvb3ewHjaC8rWdWZhR8GQhW4bunAugHL3JgBBgozpQ%2Fgd%2BTFINCWoYtsC4ASwhG%2BPnqnVEjIU4Og3y8JoVGCAm9SMLKC6bSKNeBSg6KidWM0aUGSqSZkFOMduRmIwaqUt7tyJ7TsRPk5vwHYogFK3pxjvtaSRL38%2BZ5Vop6W%2FmTI%2BR%2FynziynzAg

Steps to reproduce

Please see the link above and confirm the style attribute is not changed despite of its content is changed.

System Info

System:
    OS: macOS 14.6.1
    CPU: (8) arm64 Apple M2
    Memory: 109.88 MB / 24.00 GB
    Shell: 3.6.1 - /opt/homebrew/bin/fish
  Binaries:
    Node: 20.12.1 - /opt/homebrew/opt/node@20/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 10.5.0 - /opt/homebrew/opt/node@20/bin/npm
    pnpm: 9.11.0 - /opt/homebrew/bin/pnpm
    bun: 1.1.26 - ~/.bun/bin/bun
  Browsers:
    Chrome: 130.0.6723.117
    Safari: 17.6
  npmPackages:
    @builder.io/qwik: file:../clone/qwik/packages/qwik => 1.10.0 
    @builder.io/qwik-city: file:../clone/qwik/packages/qwik-city => 1.10.0 
    typescript: ^5.3.3 => 5.3.3 
    undici: ^5.28.4 => 5.28.4 
    vite: ^5.3.3 => 5.3.3

Additional Information

No response

@genki genki added STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working labels Nov 18, 2024
@JerryWu1234
Copy link
Contributor

@wmertens @Varixo Did you fix this bug? Maybe I can try it

@wmertens
Copy link
Member

@genki
Copy link
Contributor Author

genki commented Nov 20, 2024

@wmertens
I think this behavior is too strange to be the spec.
I wish if we could set the attributes in the closing tag.
As the second best solution, how about to append the script tag that modify attribute immediately the components that provides contexts if they have changed in the children?

<script>
document.currentScript.previousElementSibling.attributes = ... ;
</script>

@wmertens
Copy link
Member

As the second best solution, how about to append the script tag that modify attribute immediately the components that provides contexts if they have changed in the children?

This is really complex and in any case you'll get a flash of wrongly styled content + you require JS.

There are two real solutions:

  1. don't output anything until all its children were rendered
  2. change the app logic so nothing needs to change HTML that was already sent

Solution 1 uses more memory and slows down time-to-first-byte.
Solution 2 just needs some careful thinking at the beginning of writing your app.

@genki
Copy link
Contributor Author

genki commented Nov 20, 2024

@wmertens
I found the real problem.
That is there should be 2 kinds of useContextProvider but there's only 1.
The two are such that useImmutableContextProvider and useMutableContextProvider.
The former is providing readonly contexts that can ignore the update among the children.
The later is providing read/write contexts that can be updated among the children, so thus the rendering should wait the output for the mutation of it until the all user of contexts have been rendered or rather the update will be happen in the client side.
I think the later examples are mainly the placeholder components for slow contents. So the useMutableContextProvider can just delay the rendering to the client side.

@genki
Copy link
Contributor Author

genki commented Nov 20, 2024

The typical placeholder component will be vanished if its contents is not found.
The vanishment is belonging to the mutable context, it is happening at the client side.

@wmertens
Copy link
Member

@genki actually the SSR code assumes that it can emit HTML while visiting the JSX tree, and implementing what you propose would be a big hit in performance, plus it would be a lot of code changes.

Why can't you make sure that context values are fixed before you render? You can change them from tasks before you do the first output. You could also render on the client instead of on the server (with a useVisibleTask that changes a signal that rerenders).

@genki
Copy link
Contributor Author

genki commented Nov 21, 2024

@wmertens
Yes, it is possible if I use the useVisibleTask$.
But it means we have to use always useVisibleTask$ in the cases to change the value of context getting from the useContext.
Because the child component that call useContext doesn't know the change would modify the parent rendering or not.
I feel there's strong pressure to avoid using useVisibleTask$, I think it conflicts to that design.
It is good if there is something specialized useTask$ variant that runs in the client and casually usable.

@genki
Copy link
Contributor Author

genki commented Nov 21, 2024

To achieve that, there can be useMutableContext that gets the mutable context value and marks the caller component as to suspend execution of useTask$ until the client rendering (it means all useTask$ in the component act as useVisibleTask$).
And then existing useContext would be changed to be getting frozen readonly value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
STATUS-1: needs triage New issue which needs to be triaged TYPE: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants