如何简单地改变信号内的数组



这是一个有问题的工作示例。我想在信号中拼接一个现有的数组,并返回它以查看它的更新。但这行不通。我如何简单地改变数组内的信号?我不想创建新的数组,只是一个简单的拼接。文档中没有关于改变数组的例子。

import {  render } from 'solid-js/web';
import { createSignal, createEffect } from 'solid-js'
function HelloWorld() {
let [a, setA] = createSignal([])
setTimeout(() => 
setA(a => {
a.splice(0, 0, 'hello')
// this logs as requested if I uncomment this
//return ['hello']
return a
}))

createEffect(() => {
console.log(a())
})
return <div>Hello World!</div>;
}
render(() => <HelloWorld />, document.getElementById('app'))

Solid教程强烈推荐不变性:

Solid强烈建议使用浅不可变模式更新状态。通过分离读和写,我们可以更好地控制系统的反应性,而不会在通过组件层时丢失对代理的更改跟踪的风险。

一个不可变的方式来完成你想要的东西可能看起来像这样:

setA(a => ['hello', ...a])
但是,如果您确定必须改变信号,则可以在createSignal的options对象中指定Solid如何确定信号是否已更新。默认情况下,使用===操作符通过引用相等比较信号变化。您可以通过将equals设置为false来告诉Solid在调用setter后总是重新运行依赖项:
let [a, setA] = createSignal([], { equals: false });

或者你可以传递一个函数,该函数接受信号的previousnext值并返回boolean:

let [a, setA] = createSignal([], { equals: (prev, next) => {
if (/* dependents should run */) {
return false;
}
// dependents shouldn't run
return true;
} });

警告:我是Solid.js和Javascript/Typescript的新手。我下面所做的可能是一个非常糟糕的主意。

我遇到了同样的问题,并得出了以下结论。这似乎行得通。基本上保持值(例如一个非常大的数组)在一个轻量级的包装类型。重新创建包装类型,而不是重新创建数组。下面的createSignalMutable函数返回一个getter函数,它返回解包装的值,以及一个updater函数,它更新解包装的值。

import { render } from "solid-js/web";
import { createSignal, createEffect } from "solid-js";
type ThinWrapper<T> = {
internal: T;
};
function createSignalMutable<T>(value: T) {
let [getter, setter] = createSignal<ThinWrapper<T>>({ internal: value });
let getUnwrapped = () => getter().internal;
let updateUnwrapped = (mutator: (value: T) => void) =>
setter((oldWrapped: ThinWrapper<T>) => {
mutator(oldWrapped.internal);
let newWrapped: ThinWrapper<T> = { internal: value };
return newWrapped;
});
return [getUnwrapped, updateUnwrapped];
}
let initialValue: number[] = [];
let [numbers, updateNumbers] = createSignalMutable(initialValue);
createEffect(() => {
console.log("Array length is now ", [...numbers()].length);
});
updateNumbers((val) => val.push(1));
updateNumbers((val) => val.push(2));

打印

Array length is now  0
Array length is now  1
Array length is now  2

胶合板链接在这里。

最新更新