新手的问题--使用SolidJS,如何使DOM元素响应于信号更新?
我有两个实例无法按预期进行更新。
源组件
import { Component } from 'solid-js'
import { isEqual as _isEqual } from 'lodash-es'
const [getItems, setItems] = createSignal<Array<Item>>([])
const OriginComponent: Component = () => {
const updateItems = (item: Item) => {
const init = getItems()
const index = init.findIndex(i => _isEqual(i, item))
index == -1 ? init.push(item) : init.splice(index, 1)
setItems(init)
}
return (
<>
<span>Item Count: {getItems().length}</span> // << -- WILL NOT CHANGE.
<button onclick={() => updateItems(x: Item)}>Click Me</button>
</>
)
}
export { OriginComponent, getItems }远程组件
import { Component } from 'solid-js'
import { getItems } from '../OriginComponent'
const RemoteComponent: Component = () => {
return (
<p class='results'>
{getItems() ? 'Has Items' : 'Has No Items'} // << -- WILL NOT CHANGE.
</p>
)
}发布于 2022-09-09 02:44:06
根据Solid的API文档 for createSignal (在options部分):
根据JavaScript的===操作符,默认情况下,在调用信号的setter时,如果新值实际上与旧值不同,则信号只更新(并导致依赖方重新运行)。
这里就是这种情况,因为在信号中设置的数组与旧的数组相同(===)。解决方法之一是为信号设置关闭引用相等检查,如:createSignal<Array<Item>>([], { equals: false })。
另一个选项是在再次设置数组时创建一个新数组,如下所示:setItems([...init])
发布于 2022-09-11 06:03:14
组件不是DOM元素,它们在编译过程中被编译成DOM元素,但是它们有额外的可重用性。
您正在尝试更改数组,但是信号的工作方式是需要设置一个新的数组来触发状态更新。
const [items, setItems] = createSignal([]);
setInterval(() => {
setItems([ ...items(), items().length ]);
}, 1000);因此,设置一个新数组并遵循JSX规则将足以解决您的问题。
现在,为了提出这个问题,未来的证据让我们看看如何更新实体系统之外的实际DOM元素。
首先,我将创建一个DOM元素并将其附加到主体中,但是对于已经存在的DOM元素,该机制将同样工作。
import { createSignal, createEffect } from "solid-js";
// Get the DOM element
const el = document.createElement('div');
document.querySelector('body').appendChild(el);
// Signal that will be the content of our DOM element
const [count, setCount] = createSignal(0);
// I will use setInterval to update the signal for simplicity
setInterval(() => {
setCount(c => c + 1);
}, 1000);
// I will create an effect to update the element's innerText or innerHTML
// whenever the signal updates.
createEffect(() => {
el.innerHTML = count();
});在这里,我们的解决方案有一个小问题,我们创建的效果不会被任何跟踪范围所拥有,所以当它的作用域被释放时,它可能不会被释放。
最好在render函数中运行这段代码,该函数自动创建根,或者自己使用createRoot创建根,并在不需要时将其释放。
https://stackoverflow.com/questions/73655691
复制相似问题