Skip to content

Signal doesn't update for style/class attributes in a Show component #882

@ovenbreado

Description

@ovenbreado
  • Check if updating to the latest version resolves the issue

Environment

  • I am using @preact/signals-core
  • I am using @preact/signals
  • I am using @preact/signals-react

Describe the bug

Edit:
Check the comment I have below in #882 (comment) for a more minimal repro. Essentially the block caused signals within attributes to be unsubscribed (a bug within createPropUpdater from what I understand).

This is fixed by @JoviDeCroock via #883 , massive props to him!


New user of preact here! Used to solid.js but wanted something lightweight.
I've noticed that when using Show to show/hide an element that it doesn't reflect in the div attributes properly (I do ack that attributes are currently experimental). Am I doing something conceptually wrong or is this a bug? thanks!
You can reproduce this in the tutorial sandbox.

To Reproduce

Steps to reproduce the behavior:

Copy the following code snippet into https://preactjs.com/tutorial/01-vdom, then press any key a few times. The colors should follow the text on it; R for red, B for blue, G for green, but it doesn't. The s following some text is a switch to switch to the second Show when it is in the string.

The following code has a switch to two different sections when the array is rotated.

import { useRef, useEffect, useState, useCallback } from 'preact/hooks';
import { useSignal, useSignalEffect, useComputed, batch, computed, effect, signal } from '@preact/signals';
import { For, Show } from '@preact/signals/utils';

const COLOR_CLASSES = {
  "R": 'background:#f00',
  "B": 'background:#00f',
  "G": 'background:#0f0',
};

export function App(props) {
  const sigArray = useSignal([
    useSignal('R'),
    useSignal('Bs'),
    useSignal('G'),
    useSignal('Rs')
  ]); // Array of 4 cubes, s is a special mark, renders a smaller div

  useEffect(() => {
    window.addEventListener('keydown', (e) => {
      let keep = sigArray.value[0].value;
      sigArray.value[0].value = sigArray.value[1].value
      sigArray.value[1].value = sigArray.value[2].value
      sigArray.value[2].value = sigArray.value[3].value
      sigArray.value[3].value = keep
    });
  }, []);
  
  return (
    <div class="">
      <For each={sigArray}>
        {(col, colIndex) => {
          return (
            <div>
              <Show when={useComputed(() => col.value?.charAt(1) !== "s")}>
                <div style={useComputed(() => `width:30px;height:30px; ${COLOR_CLASSES[col.value?.charAt(0)]}`)}>
                  {col}
                </div>
              </Show>
              <Show when={useComputed(() => col.value?.charAt(1) === "s")}>
                <div style={useComputed(() => `width:20px;height:20px; ${COLOR_CLASSES[col.value?.charAt(0)]}`)}>
                  {col}
                </div>
              </Show>
            </div>
          );
        }}
      </For>
    </div>
  );
}

render(<App />, document.getElementById('app'));

Expected behavior
Signal should update background colors attribute according to the letters.

Thanks for taking a look into this!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions