skip to Main Content

I met an issue that my todo list never update 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 to react hooks. Can anyone help? Thanks!

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}
        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

2

Answers


  1. Make sure to use the value property when accessing the signal values. The code below will resolve the issue, and now the todo list should update when you add a new todo item.

    Solution:

    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 signal value
      }
    
      return (
        <div>
          Create a todo list with signals.
          <br />
          <br />
          <input
            type="text"
            value={newTodo.value} {/* Access value property of the signal */}
            onChange={(e) => (newTodo.value = e.target.value)}
            placeholder="Type to add..."
          />
          <button type="submit" onClick={addNewTodo}>
            add new todo
          </button>
          <br />
          {/* Access value property of the signals */}
          {newTodo.value}, {todos.value}
          <ul>
            {todos.value.map((item, index) => (
              <li key={index}>{item}</li>
            ))}
          </ul>
        </div>
      )
    }
    
    Login or Signup to reply.
  2. signal(...) creates new instance on each render. When you update it, rerender happens and then signal gives you the initial instance. You should not use it inside component. Move it outside or use useSignal

    https://preactjs.com/guide/v10/signals/#local-state-with-signals

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search