SolidJS:输入字段在键入时失去焦点

Jos*_*ong 6 arrays focus input solid-js

我有一个关于 SolidJS 的新手问题。我有一个包含对象的数组,例如待办事项列表。我将其呈现为一个列表,其中包含输入字段以编辑这些对象中的属性之一。当在其中一个输入字段中输入内容时,输入会直接失去焦点。

如何防止输入时失去焦点?

以下是演示该问题的 CodeSandbox 示例:https://codesandbox.io/s/6s8y2x ?file=/src/main.tsx

这是演示该问题的源代码:

import { render } from "solid-js/web";
import { createSignal, For } from 'solid-js'

function App() {
  const [todos, setTodos] = createSignal([
    { id: 1, text: 'cleanup' },
    { id: 2, text: 'groceries' },
  ])

  return (
    <div>
      <div>
        <h2>Todos</h2>
        <p>
          Problem: whilst typing in one of the input fields, they lose focus
        </p>
        <For each={todos()}>
          {(todo, index) => {
            console.log('render', index(), todo)
            return <div>
              <input
                value={todo.text}
                onInput={event => {
                  setTodos(todos => {
                    return replace(todos, index(), {
                      ...todo,
                      text: event.target.value
                    })
                  })
                }}
              />
            </div>
          }}
        </For>
        Data: {JSON.stringify(todos())}
      </div>
    </div>
  );
}

/*
 * Returns a cloned array where the item at the provided index is replaced
 */
function replace<T>(array: Array<T>, index: number, newItem: T) : Array<T> {
  const clone = array.slice(0)
  clone[index] = newItem
  return clone
}

render(() => <App />, document.getElementById("app")!);
Run Code Online (Sandbox Code Playgroud)

更新:我已经制定了一个 CodeSandbox 示例,其中包含该问题和三个建议的解决方案(基于两个答案):https ://codesandbox.io/s/solidjs-input-field-loses-focus-when-typing-itttzy ?file=/src/App.tsx

the*_*nav 9

<For>组件通过引用输入数组的键项。当您使用 更新待办事项中的待办事项时replace,您正在创建一个全新的对象。然后,Solid 将新对象视为完全不相关的项目,并为其创建一个新的 HTML 元素。

您可以createStore改为使用并仅更新 todo 对象的单个属性,而不更改对其的引用。

const [todos, setTodos] = createStore([
   { id: 1, text: 'cleanup' },
   { id: 2, text: 'groceries' },
])
const updateTodo = (id, text) => {
   setTodos(o => o.id === id, "text", text)
}
Run Code Online (Sandbox Code Playgroud)

或者使用替代控制流组件来映射输入数组,该组件采用显式键属性: https://github.com/solidjs-community/solid-primitives/tree/main/packages/keyed#Key

<Key each={todos()} by="id">
   ...
</Key>
Run Code Online (Sandbox Code Playgroud)