Search code examples
javascriptreactjsfrontendsignalspreact

why doesn't signal re-render when add a new item? Preact signals


I'm learning signals features and met some issues:

  1. if set value={newTodo.value} then I cant type in input field, there would be only one character be typed in.
  2. if set value={newTodo}, I can type in input field, but my todo list todos never update/re-render in UI when I click the button to add a new todo item even tho console.log shows the list is updated already.

But everything would works fine if i change back to react hooks. Can anyone help? Thanks!

I also created a sandbox for this issue.

import { signal, effect } from "@preact/signals-react"
import { useState } from "react"

export default function SignalsTodolist() {
  const todos = signal(["eat", "sleep", "play video game"])
  const newTodo = signal("")

  const addNewTodo = (e) => {
    e.preventDefault()
    todos.value = [...todos.value, newTodo.value]
    console.log(todos.value)
    newTodo.value = "" // Use setNewTodo to update the state
  }

  // const resetToto = () => {
  //   newTodos(["eat", "sleep", "play video game"])
  // }

  return (
    <div>
      Create a todo list with signals。
      <br />
      <br />
      <input
        type="text"
        value={newTodo}.   // highlight
        onChange={(e) => (newTodo.value = e.target.value)}
        placeholder="Type to add..."
      />
      <button type="submit" onClick={addNewTodo}>
        add new todo
      </button>
      <br />
      {newTodo}, {todos} {/* To display the array */}
      <ul>
        {todos.value.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  )
}

enter image description here


Solution

  • You're running into two usage issues at once:

    1. You cannot use signal or computed in components. Use useSignal or useComputed.

    When creating signals within a component, use the hook variant: useSignal(initialValue).

    https://preactjs.com/guide/v10/signals/#signalinitialvalue

    1. You've skipped over the React integration instructions. Usage changed in v2, you need to pick between using the Babel plugin or useSignals().