A Way for Selective Reactive Object #2398
Replies: 3 comments
-
For performance concern in using Proxy, we can also have the https://playground.solidjs.com/anonymous/18190ce2-0a27-4348-8b7e-a1bd8b721433 import {render } from "solid-js/web";
import { createSignal, For } from "solid-js";
function App() {
// Initialize an array of objects using createSignal
let items0 = [
{ id: 1, name: "Item 1", quantity: 5 },
{ id: 2, name: "Item 2", quantity: 2 },
];
;(()=>{
const sWrapper = (w) => {
const [singalGet, singalSet] = createSignal(1);
return function (e = 0) {
e ? Promise.resolve(x => (x & 1073741823) + e).then(singalSet) : singalGet();
return w;
};
}
Object.prototype.valueOf = function () {
return (this.valueOf = sWrapper(this))(...arguments)
}
})();
// Add a new item
const addItem = () => {
const newId = Date.now(); // or some other unique ID
const newItem = {
id: newId,
name: `Item ${newId}`,
quantity: 1,
};
items0.valueOf(1).push(newItem);
};
// Remove an item by ID
const removeItem = (id) => {
let i =0;
for(const item of items0){
if(item.id === id){
items0.valueOf(1).splice(i, 1);
break;
}
i++;
}
};
// Increment the quantity of a specific item
const increment = (id) => {
for(let i =0;i<items0.length ; i++){
const item = items0[i];
if(item.id === id){
(item).valueOf(1).quantity += 1;
// itemsModifiable[i]= { ...item, quantity: item.quantity + 1 }
break;
}
}
};
// Decrement the quantity of a specific item
const decrement = (id) => {
for(let i =0;i<items0.length ; i++){
const item = items0[i];
if(item.id === id){
(item).valueOf(1).quantity -= 1;
// itemsModifiable[i]= { ...item, quantity: item.quantity - 1 }
break;
}
}
};
return (
<div>
<h1>Interactive Array of Objects</h1>
<button onClick={addItem}>Add New Item</button>
<ul>
<For each={(items0).valueOf()}>
{(item) => (
<li>
<strong>{item.name}</strong> (Quantity: {(item).valueOf().quantity})
{" "}
<button onClick={() => increment(item.id)}>+</button>
<button
onClick={() => decrement(item.id)}
disabled={(item).valueOf().quantity === 0}
>
-
</button>
{" "}
<button onClick={() => removeItem(item.id)}>Remove</button>
</li>
)}
</For>
</ul>
</div>
);
}
render(() => <App />, document.getElementById("app")); |
Beta Was this translation helpful? Give feedback.
-
To avoid global property assignment, we might use https://playground.solidjs.com/anonymous/6da36dbc-15fb-4087-94d1-012bc4d9e5fd import {render } from "solid-js/web";
import { createSignal, For } from "solid-js";
function App() {
// Initialize an array of objects using createSignal
let items0 = [
{ id: 1, name: "Item 1", quantity: 5 },
{ id: 2, name: "Item 2", quantity: 2 },
];
const { R, W } = (() => {
/*
const sWrapper = (w) => {
const [singalGet, singalSet] = createSignal(1);
return function (e = 0) {
e ? Promise.resolve(x => (x & 1073741823) + e).then(singalSet) : singalGet();
return w;
};
};
*/
// collective version such that
// `W(o).attr1 = 1; W(o).attr2 = 2; W(o).attr1 = 3; W(o).attr2 = 4;` will only execute update once after the last operation (`.attr2=4`)
// if there are two objects, say o1, o2, then the order might be different
//
// `W(o1).attr1 = 1; W(o2).attr2 = 2; W(o2).attr2 = 4;W(o1).attr1 = 3; `
//
// first Promise: o1 changed first (attr1=3) => o2 changed second (attr2=4)
// last Promise: o2 changed first (attr2=4) => o1 changed second (attr1=3)
// first and last Promise: o1 -> o2 -> o2 -> o1
const sWrapper = (w) => {
let u = 2;
const [singalGet, singalSet] = createSignal(1);
// const p = (m) => singalSet(u); // first Promise
// const p = (m) => m === u && singalSet(u); // last Promise
const p = (m) => singalSet(u + (m === u)); // first and last Promise
return function (e = 0) {
e
? Promise.resolve((u = (u & 1073741823) + e)).then(p)
: singalGet();
return w;
};
};
const valueOf_ = Object.prototype.valueOf;
const R = (x) => {
let valueOf = x.valueOf;
if (valueOf === valueOf_) valueOf = x.valueOf = sWrapper(x);
return valueOf();
};
const W = (x) => {
let valueOf = x.valueOf;
if (valueOf === valueOf_) valueOf = x.valueOf = sWrapper(x);
return valueOf(1);
}
return { R, W };
})();
// Add a new item
const addItem = () => {
const newId = Date.now(); // or some other unique ID
const newItem = {
id: newId,
name: `Item ${newId}`,
quantity: 1,
};
W(items0).push(newItem);
};
// Remove an item by ID
const removeItem = (id) => {
let i =0;
for(const item of items0){
if(item.id === id){
W(items0).splice(i, 1);
break;
}
i++;
}
};
// Increment the quantity of a specific item
const increment = (id) => {
for(let i =0;i<items0.length ; i++){
const item = items0[i];
if(item.id === id){
W(item).quantity += 1;
// itemsModifiable[i]= { ...item, quantity: item.quantity + 1 }
break;
}
}
};
// Decrement the quantity of a specific item
const decrement = (id) => {
for(let i =0;i<items0.length ; i++){
const item = items0[i];
if(item.id === id){
W(item).quantity -= 1;
// itemsModifiable[i]= { ...item, quantity: item.quantity - 1 }
break;
}
}
};
return (
<div>
<h1>Interactive Array of Objects</h1>
<button onClick={addItem}>Add New Item</button>
<ul>
<For each={R(items0)}>
{(item) => (
<li>
<strong>{item.name}</strong> (Quantity: {R(item).quantity})
{" "}
<button onClick={() => increment(item.id)}>+</button>
<button
onClick={() => decrement(item.id)}
disabled={R(item).quantity === 0}
>
-
</button>
{" "}
<button onClick={() => removeItem(item.id)}>Remove</button>
</li>
)}
</For>
</ul>
</div>
);
}
render(() => <App />, document.getElementById("app")); |
Beta Was this translation helpful? Give feedback.
-
One benefit is that, for some complicated functions, we might need to have some reading then do the setting. for example, const [objectZ, objectZset] = createStore({...})
// ....
const clearSetting =()=>{
if( match1(objectZ.attr1) && match2(object.attr2) && ...){
objectZset({ ..... }
}
} in this example, we do not need any read signal subscription in this |
Beta Was this translation helpful? Give feedback.
-
When using
createStore
, it is convenient because the children of the object will have reactivity.However, every "read" of its nested object will make the data reactive. It somehow pollute the raw data.
I would like to show a way for handling it. It does not pollute the raw data, and no symbol part to the data object.
First, start with the
sWrapper
This will create a function that do the setter and getter.
so,
this will make the DOM change as set signal is sent and get signal in the render will update the corresponding content.
the wrapped object can be stored for reusing. so the calling will be
wrap(obj1).somethingChanging
for changing content (reactive) andobj1.somethingFixed
for static content (non-reactive).This is so called "selective reactive".
Here we will have something like
and
As you see, the set/get signals are only involved in the
mP(...)
.For the implementation of
mP
, please see the example code.Usage
Let say I have a list
The reactive part should be only the name and text. I don't need the data1 and its nested levels become reactive (just read-only).
If I need to amend the entire entry, I will do the Object.assign so that the entire entity will be updated.
(or
splice(idx, 1, newEntry)
)Example Code
https://playground.solidjs.com/anonymous/64812e80-9f35-4bd7-8f16-19e924356e43
Beta Was this translation helpful? Give feedback.
All reactions