#update signal inside server$

6 messages · Page 1 of 1 (latest)

solar trench
#

I'm trying to update a state using server$ for the first time the user visits the website, but it is saying that the signal is readonly and can't be updated

my code:

const syncState = server$(async function (state) {
  const sessionId = this.cookie.get("session-id");
  if (!sessionId) return;
  const storedValue = await redisClient.get(`session:${sessionId.value}`);
  if (storedValue) {
    Object.assign(state, JSON.parse(storedValue));
  }
});

const state = useStore<PresentationStore["state"]>(() => ({
    id: "0",
  }));

syncState(state)

throws:

/home/patrickkmatias/repos/shaliah/node_modules/@qwik.dev/core/dist/core.mjs:1128
  target[prop] = value;
               ^

TypeError: Cannot assign to read only property 'id' of object '#<Object>'
    at setNewValueAndTriggerEffects (/home/patrickkmatias/repos/shaliah/node_modules/@qwik.dev/core/dist/core.mjs:1128:16)
    at StoreHandler.set (/home/patrickkmatias/repos/shaliah/node_modules/@qwik.dev/core/dist/core.mjs:1065:9)
    at Function.assign (<anonymous>)
    at Object.eval (/home/patrickkmatias/repos/shaliah/src/contexts/PresentationContext.tsx:23:29)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async Object.qrl2 (/home/patrickkmatias/repos/shaliah/node_modules/@qwik.dev/core/dist/core.mjs:7913:20)
    at async qrl2 (/home/patrickkmatias/repos/shaliah/node_modules/@qwik.dev/core/dist/core.mjs:7913:20)

Node.js v22.14.0

it happens even with a plain object, without being a signal.

#

I couldn't replicate it as @qwik.dev/router is not available in the sandbox, to import server$

ruby scroll
#

have you considered using sharemap?

short pivot
#

useStore is something that exists inside the scope of a component (it lives inside the DOM), whereas server$ are functions defined in the scope of your server (it lives in your actual server). So they live in 2 completely different world. Meaning you can't directly mutate a server$ param.

+-------+     server$     +--------+
|  DOM  | ------------->  | Server |
+-------+                 +--------+

It's not always the case, but you should see this server$ call as a network call. Meaning you have a request (the params of your function) and a response (the return statement). So you can't modify the request (params), you need to return a response instead.

Knowing that, you will have different mechanism to achieve the state update, but a very simple one would be this:

const getSession = server$(async function () {
  const sessionId = this.cookie.get("session-id");
  if (!sessionId) return;
  const storedValue = await redisClient.get(`session:${sessionId.value}`);

  return JSON.parse(storedValue);
});

const YourPage = component$(() => {
  const state = useStore<PresentationStore["state"]>({
    id: "0",
  });

  useTask$(async () => {
    const session = await getSession();
    if (session) {
      Object.assign(state, session);
    }
  });

  return (...);
});

or something along those lines

solar trench
#

hey @short pivot, thanks for the class!

as useTask works first in server I thought that it was fine modifying anything involving it with a server$ call

but with this suggestion I was able to continue

again, thanks 🙂