preactjs / signals

Manage state with style in every framework
https://preactjs.com/blog/introducing-signals/
MIT License
3.64k stars 89 forks source link

Creating a empty signal and updating it make the application stop re-rendering #419

Open fbzz opened 10 months ago

fbzz commented 10 months ago

So using react with vite, we can even use the example from preact, the first update will work, and after that it will stop

import { signal, computed } from "@preact/signals-react";

const todos = signal([
]);

const completedCount = computed(() => {
  return todos.value.filter(todo => todo.completed).length;
});

const newItem = signal("");

function addTodo() {
  todos.value = [...todos.value, { text: newItem.value, completed: false }];
  newItem.value = ""; // Reset input value on add
}

function removeTodo(index) {
  todos.value.splice(index, 1)
  todos.value = [...todos.value];
}

function TodoList() {
  const onInput = event => (newItem.value = event.target.value);

  return (
    <>
      <input type="text" value={newItem.value} onInput={onInput} />
      <button onClick={addTodo}>Add</button>
      <ul>
        {todos.value.map((todo, index) => {
          return (
            <li>
              <input
                type="checkbox"
                checked={todo.completed}
                onInput={() => {
                  todo.completed = !todo.completed
                  todos.value = [...todos.value];
                }}
              />
              {todo.completed ? <s>{todo.text}</s> : todo.text}{' '}
              <button onClick={() => removeTodo(index)}>❌</button>
            </li>
          );
        })}
      </ul>
      <p>Completed count: {completedCount.value}</p>
    </>
  );
}
monaye commented 8 months ago

since you are modifying the original array with the splice, I think signal will trigger the re-render. can you try remove the todos.value = [...todos.value]? or try with toSpliced.

namtv95 commented 7 months ago

Same issue here, when you init signal with an empty array

  1. With useSignal([]) syntax, it cannot update value, it shows "Cannot read properties of undefined (reading 'length')" error
  2. With signal([]), it only updates at first time, at second time it won't work
XantreDev commented 7 months ago

Can you provide stackblitz repro to check?

XantreDev commented 7 months ago

Btw, you should not mutate values of signals. Signals doesn't reacting on mutations. Use .toSpliced