为什么添加新项目时没有信号重新渲染?预反应信号

问题描述 投票:0回答:2

我正在学习

signals
功能并遇到了一些问题:

  1. 如果设置了
    value={newTodo.value}
    那么我就无法在输入字段中输入内容,只能输入一个字符。
  2. 如果设置了
    value={newTodo}
    ,我可以在输入字段中输入内容,但当我单击按钮添加新的待办事项时,我的待办事项列表
    todos
    永远不会在 UI 中更新/重新渲染,即使
    console.log
    显示列表已更新已经。

但是如果我改回反应钩子,一切都会正常。有人可以帮忙吗?谢谢!

我还为此问题创建了一个沙箱

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

javascript reactjs frontend signals preact
2个回答
1
投票

signal(...)
在每个渲染上创建新实例。当您更新它时,会发生重新渲染,然后信号会为您提供初始实例。您不应该在组件内部使用它。将其移到外面或使用
useSignal

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


0
投票

经过一些研究......也许尝试使用

batch
来确保项目已更新/重新渲染。

preact 非常脆弱,因为最小的东西都可能搞砸 - 我一直在弄乱几个不同的沙箱,这似乎是最好的工作示例,但对于一个简单的待办事项列表来说有很多开销https:// codesandbox.io/p/sandbox/preact-signals-react-5qcp8r

TodoList.js

import { signal, computed, batch } from "@preact/signals-react";
import { useAppState } from "./AppStateContext";

const newItem = signal("");

export default function TodoList() {
  const { todos, addTodo, removeTodo } = useAppState();
  const completedCount = computed(() => {
    return todos.value.filter((todo) => todo.completed).length;
  });

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

  const onAddClick = () => {
    batch(() => {
      addTodo(newItem);
      newItem.value = "";
    });
  };

  return (
    <>
      <input type="text" value={newItem.value} onInput={onInput} />
      <button style={{ marginLeft: "10px" }} onClick={onAddClick}>
        Add
      </button>
      <ul style={{ textAlign: "left" }}>
        {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
                style={{ marginLeft: "10px", color: "red" }}
                onClick={() => removeTodo(index)}
              >
                x
              </button>
            </li>
          );
        })}
      </ul>
      <p>Completed count: {completedCount.value}</p>
    </>
  );
}

AppContext.js

import React, { useContext } from "react";
import { signal } from "@preact/signals-react";
const AppState = React.createContext();

function AppStateProvider(props) {
  const todos = signal([
    { text: "eat", completed: true },
    { text: "sleep", completed: false },
    { text: "rave", completed: false },
    { text: "repeat", completed: false }

  ]);
  function addTodo(newItem) {
    todos.value = [...todos.value, { text: newItem.value, completed: false }];
  }

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

  return (
    <AppState.Provider value={{ todos, addTodo, removeTodo }}>
      {props.children}
    </AppState.Provider>
  );
}

function useAppState() {
  const appState = useContext(AppState);
  if (!appState) {
    throw new Error("useAppState must be used within a AppStateProvider");
  }
  return appState;
}

export { AppStateProvider, useAppState };

据我从使用 preact 的公司同事那里听到的消息,除非你每次都完美地使用它,否则信号等可能会成为一场噩梦。另外,您的代码问题可能是因为 preact 与您的框架交互的方式,因为正如 preact 文档所述,当您更新值时,它应该导致重新渲染,但显然不是

即使在给出的示例中,状态也没有按预期完全工作...尝试删除未选中的项目,然后检查新项目或在尝试删除未选中的项目后添加项目..您会看到一些明显的渲染问题..preact 也是suuuuper new所以除非你必须使用它,否则可能会踢它并密切关注它,直到它与其他框架(如反应)相比具有更高的稳定性

© www.soinside.com 2019 - 2024. All rights reserved.