admin管理员组文章数量:1327849
const App: Component = () => {
const [obj, setObj] = createSignal({
name: "John",
age: 30,
})
createEffect(
on(
() => obj().name,
(value) => {
console.log("name", value)
}
)
)
return ()=>(<button onClick={()=> setObj(obj=> ({ ...obj, age: obj.age + 1}))}>+</button>)
}
When I change age
, createEffect
will also be triggered, I just want to listen on name
, similar to watch
in Vue3
.
function setup(){
const obj = reactive({
name: "John",
age: 30,
})
watch(()=> obj.name,(value)=>{ console.log("name", value) })
}
Any good ideas?
const App: Component = () => {
const [obj, setObj] = createSignal({
name: "John",
age: 30,
})
createEffect(
on(
() => obj().name,
(value) => {
console.log("name", value)
}
)
)
return ()=>(<button onClick={()=> setObj(obj=> ({ ...obj, age: obj.age + 1}))}>+</button>)
}
When I change age
, createEffect
will also be triggered, I just want to listen on name
, similar to watch
in Vue3
.
function setup(){
const obj = reactive({
name: "John",
age: 30,
})
watch(()=> obj.name,(value)=>{ console.log("name", value) })
}
Any good ideas?
Share Improve this question edited Aug 26, 2022 at 7:20 clencat asked Aug 22, 2022 at 3:56 clencatclencat 1595 bronze badges2 Answers
Reset to default 6SolidJS will not keep track of individual properties of a signal object.
Also you are overwriting the object every time a value changes when destructuring it (aka. {...obj, }).
If you want createEffect to keep track of your individual properties try createStore.
Here's your example written with createStore instead of createSignal
import {createStore} from 'solid-js/store'; // <- This is very important
const App: Component = () => {
const [obj, setObj] = createStore({
name: "John",
age: 30,
})
createEffect(() => console.log(obj.name));
return (<button onClick={setObject('age', obj.age + 1)}>+</button>)
)
}
if you run this example, you'll see that console.log(obj.name) will only run once, this is because solid-js will keep track of individual properties when saving them on a createStore
Signals are atomic values providing unidirectional data flow, meaning you update a signal by setting a new value. Even if you pass the same properties, you will be setting a new object, because objects are pared by reference in JavaScript, hence triggering an update.
That being said, there are multiple ways or workarounds to keep track of an individual property of an object stored in signal.
Using a store.
createStore
uses a proxy internally and provides ways to track individual properties. You can useproduce
, an Immer inspried API for localized mutations hence update certain properties only.You can create a memoized signal that tracks an individual property on an object. Here only changing the age re-runs the effect however updating the name has no effect:
import { render } from "solid-js/web";
import { createSignal, createMemo, createEffect } from "solid-js";
function App() {
const [person, setPerson] = createSignal({ name: "John Doe", age: 20 });
const handleClick = () => setPerson({ name: "Jenny Doe", age: 20 });
const age = createMemo(() => person().age);
createEffect(() => {
console.log("Age is updated", age());
});
return (
<button type="button" onClick={handleClick}>
{JSON.stringify(person())}
</button>
);
}
render(App, document.getElementById("app")!);
- Use
on
utility fromsolid-js
:
import { render } from "solid-js/web";
import { createSignal, createEffect, on } from "solid-js";
import { createStore } from "solid-js/store";
function App() {
const [person, setPerson] = createStore({ name: 'John Doe', age: 30 });
const increment = () => setPerson(p => ({ ...p, age: p.age + 1 }));
createEffect(on(() => person.name, () => {
console.log('Tracking name');
}));
createEffect(on(() => person.age, () => {
console.log('Tracking age');
}));
return (
<button type="button" onClick={increment}>
{person.name} {person.age}
</button>
);
}
render(App, document.getElementById("app")!);
This method also works for a signal:
import { render } from "solid-js/web";
import { createSignal, createEffect, on } from "solid-js";
function App() {
const [person, setPerson] = createSignal({ name: 'John Doe', age: 30 });
const increment = () => setPerson(p => ({ ...p, age: p.age + 1 }));
createEffect(on(() => person.name, () => {
console.log('Tracking name');
}));
createEffect(on(() => person().age, () => {
console.log('Tracking age');
}));
return (
<button type="button" onClick={increment}>
{person().name} {person().age}
</button>
);
}
render(App, document.getElementById("app")!);
- You can use equals argument in createSignal:
import { render } from "solid-js/web";
import { createSignal, createEffect, on } from "solid-js";
function App() {
const [person, setPerson] = createSignal(
{ name: "John Doe", age: 20 },
{ equals: (prev, next) => prev.age === next.age }
);
const handleClick = () => setPerson({ name: "Jenny Doe", age: 20 });
createEffect(() => {
console.log("Age is updated", person());
});
return (
<button type="button" onClick={handleClick}>
{JSON.stringify(person())}
</button>
);
}
render(App, document.getElementById("app")!);
These are out of the box solution but since Solid is pretty flexible and quite permissive you can implement your own logic if you like.
本文标签: javascriptHow to listen to only a certain value of an object in solidjsStack Overflow
版权声明:本文标题:javascript - How to listen to only a certain value of an object in solid-js? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742216557a2434671.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论