I'm trying to modify an element of a SolidJS store using the SetStoreFunction (setExpressions), so that the View for the store's values are updated, e.g. when text is entered into a text field.
I originally thought the problem had to do with calling the SetStoreFunction itself, but the console logging in getExpressionSetValue
shows that the setting is working. So the issue is with the updating of the View after the set takes place.
My expectation was that it would automatically be handled when using a store. I'm not sure if I'm using it wrong or what the problem is
Full Code:
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;
Update 8/8:
I tried switching to native UI elements instead of using Kobalte and now it works. E.g.:
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>
)
}
and
<button type="button" onClick={addExpression}>+</button>
I still don't understand what's going on here and would like to fix the Kobalte version, because I'd like to use Kobalte