我正在try 使用SetStoreFunction(SetExpressions)修改SolidJS存储的一个元素,以便更新存储的值的视图,例如在文本字段中输入文本时.

我最初认为问题与调用SetStoreFunction本身有关,但登录getExpressionSetValue的控制台显示设置正在工作.因此,问题出在设置发生后更新视图.

我的期望是,在使用store 时,它会自动处理.我不确定是我用错了,还是出了什么问题

完整代码:

import { createStore } from "solid-js/store";
import type { Component } from 'solid-js'
import { For } from 'solid-js';
import { TextField } from "@kobalte/core"
import { Button } from "@kobalte/core"

interface Expression {
  id: number,
  label: string,
  value: string,
}

interface ExpressionViewProps extends Expression {
  removeExpression: () => void
  setValue: (value:string) => void
}

const ExpressionView: Component<ExpressionViewProps> = (props) => {

  return (
    <div>
      <TextField.Root 
        value={props.value} //todo why doesn't this value update automatically?
        onChange={props.setValue}>
        <TextField.Label>
          {props.label}
        </TextField.Label>
        <br/>
        <TextField.Input />
        <TextField.Description />
        <TextField.ErrorMessage />
      </TextField.Root>
      <Button.Root class="button" onClick={props.removeExpression}>-</Button.Root>
    </div>
  )
}

const App: Component = () => {

  const [expressions, setExpressions] = createStore<Expression[]>([])
  let expressionId = 0

  const addExpression = () => {
    setExpressions(() => {
      const id = ++expressionId
      return [...expressions, {id: id, label: `Expression ${id}`, value: "inital value 0"}]
    })
  }

  const getRemoveExpression = (id: number) => {
    return () => {
      setExpressions(() =>
        expressions.filter(expression => expression.id != id)
      )
    }
  }

  const getExpressionSetValue = (id: number) => {
    return (value: string) => {
      console.log(value)
      setExpressions(expression => expression.id == id, 'value', value)
      console.log(expressions)
    }
  }

  return (
    <div>
      <For each={expressions}>{(expression) => {
        const expressionViewProps: ExpressionViewProps = {
          ...expression,
          removeExpression: getRemoveExpression(expression.id),
          setValue: getExpressionSetValue(expression.id),
        }
        return <ExpressionView {...expressionViewProps}/>
      }}</For>
      <Button.Root class="button" onClick={addExpression}>+</Button.Root>
  </div>
  )
}

export default App;


更新8/8:

我try 切换到原生UI元素,而不是使用Kobalte,现在它起作用了.例如:

const ExpressionView: Component<ExpressionViewProps> = (props) => {
  return (
    <div>
      <input
        value={props.value}
        onInput={(e) => props.setValue(e.target.value)}
      />
      <button type="button" onClick={() => props.removeExpression()}>-</button>
    </div>
  )
}

      <button type="button" onClick={addExpression}>+</button>

I still don't underst和 what's going on here 和 would like to fix the Kobalte version, because I'd like to use Kobalte

推荐答案

我还没有测试过这一点,但我认为以下内容应该会对你有所帮助:

一般来说,有两种类型的输入组件--"受控"和"非受控".

  • 在受控模式下,用户输入会触发事件,但只有在代码更新状态时才会更新状态.因此,如果用户开始输入,则会触发输入事件,您将更新值属性,然后输入字段也会更新以显示新值.
  • 在非受控模式下,输入字段使用新的(用户给定的)值更新,然后(或同时)触发onInput.在此场景中,the value prop and field can be out of sync:如果值属性从不更新,则输入并不关心,它只显示用户键入的值.(但是,如果值属性更改为与输入中当前显示的值不同的值,则输入将更新为值属性).

在Solid中,输入元素(以及一般的DOM元素)的行为不受控制.然而,在Kobalte中,如果您提供value个props ,则组件将受到控制.在您的例子中,我相信传递给ExpressionView的值属性永远不会改变(我马上就会讲到这一点),所以显示也永远不会改变.使用常规输入没有这个问题,因为非受控模式工作得很好,不需要更新价值属性.

现在,至于传递给ExpressionView的值没有更新的原因,问题是如何创建ExpressionViewProps

<For each={expressions}>{(expression) => {
  const expressionViewProps: ExpressionViewProps = {
    ...expression,
    removeExpression: getRemoveExpression(expression.id),
    setValue: getExpressionSetValue(expression.id),
  }
  return <ExpressionView {...expressionViewProps}/>
}}</For>

通常,存储跟踪properties被访问的位置,如果属性在react 作用域内被访问,则当存储中的值被更新时,该作用域将重新运行.因此,在您的代码中,使用...expression访问expression对象上的每个属性,并将键/值分配给您正在创建的新对象,但这isn't发生在react 作用域中(for的回调不是react 作用域),因此对存储的更新不会导致回调重新运行.

相反,我建议做的是

return <ExpressionView removeExpression={getRemoveExpression(expression.id)} setValue={getExpressionSetValue(expression.id)} {...expression}/>

因为Solid的编译器将分析JSX(编译器only分析JSX),并发现{...expression}可能是react 性的,并创建延迟属性访问(因此访问将最终跟踪使用props.value的位置),而不是展开.

Javascript相关问答推荐

文件阅读器未读取一个文件

JavaScript:循环访问不断变化的数组中的元素

是什么原因导致此Angular 16应用程序中类型错误时属性结果不存在?

在JavaScript中声明自定义内置元素不起作用

将自定义排序应用于角形数字数组

在拖放时阻止文件打开

html + java script!需要帮助来了解为什么我得到(无效的用户名或密码)

如何将Openjphjs与next.js一起使用?

当Redux提供程序访问Reduxstore 时,可以安全地从Redux提供程序外部调用钩子?

简单的PayPal按钮集成导致404错误

为什么useState触发具有相同值的呈现

在运行时使用Next JS App Router在服务器组件中运行自定义函数

在Reaction中的handleSubmit按钮内,useSelector值仍然为空

如何在.NET Core中将chtml文件链接到Java脚本文件?

在css中放置所需 colored颜色 以填充图像的透明区域

Puppeteer上每页的useProxy返回的不是函数/构造函数

元素字符串长度html

AddEventListner,按键事件不工作

在表单集中保存更改时删除';禁用';

ReferenceError:无法在初始化之前访问setData