S
SolidJSā€¢5mo ago
d34dbug

Reactivity lost if awaited function precedes?

So this is reactive (reloads the desired componant), but is out of order from what I need to happen.
<button id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
props.setActiveSession(sessionSelected());
await set_session({id:sessionSelected()});
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
<button id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
props.setActiveSession(sessionSelected());
await set_session({id:sessionSelected()});
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
This does not reload the desired component, but is the correct order for what I need to happen. How do I resolve this situation?
<button id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
await set_session({id:sessionSelected()});
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
<button id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
await set_session({id:sessionSelected()});
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
I need to ensure that the backend is updated first because the component that is loaded fetches the updated data as a createResource, so I need to make sure that data is correct. I am trying to avoid attempting to keep state in sync between the backend and frontend by using the backend as the source of truth. Since this is a Tauri app, since the backend is local, delays are not an issue.
19 Replies
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
what does set_session and props.setActiveSession do? (also can you syntax highlight with ```tsx ?)
d34dbug
d34dbugā€¢5mo ago
set_session is a tauri function calling the backend:
export async function set_session({ id }) {
let msg = {
id: id
};
let val = await invoke("set_session", { "msg": JSON.stringify(msg) });
return val
}
export async function set_session({ id }) {
let msg = {
id: id
};
let val = await invoke("set_session", { "msg": JSON.stringify(msg) });
return val
}
props.setActiveSession is the setter for a signal in the parent component pretty sure you can think of the set_session as a fetch. The difference is that it's fetching from a local instance of the Tauri backend: string goes out, string comes back. in case it matters this is in the parent component:
const fetchSession = async () => {
const sess = await get_session_id(); //this needs to return undefined if error
return sess;
};
const fetchScope = async () => {
const scope = await get_session_scope(); //this needs to return undefined if error
return scope;
};

export default function MainContents(props) {
const [activeSession, setActiveSession] = createSignal();
const [sessionId] = createResource(activeSession,fetchSession);
const [currentScope]=createResource(sessionId,fetchScope);
const fetchSession = async () => {
const sess = await get_session_id(); //this needs to return undefined if error
return sess;
};
const fetchScope = async () => {
const scope = await get_session_scope(); //this needs to return undefined if error
return scope;
};

export default function MainContents(props) {
const [activeSession, setActiveSession] = createSignal();
const [sessionId] = createResource(activeSession,fetchSession);
const [currentScope]=createResource(sessionId,fetchScope);
The idea is to use the activeSession as a trigger to validate that the session in the backend which then triggers a validation of whether the scope is set in the backend. These are used to conditionally render the parent component. It sounds convoluted and it kinda is, but it's because I am trying to rely on state on the backend, not the frontend.
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
mm strange, from the looks of it, it should be fine. I know sometimes await can do funky stuff in solid, for example using it inside an effect can cause bugs (any signal called after await won't cause the effect to re-run), but I don't think that's what's happening here.
d34dbug
d34dbugā€¢5mo ago
not sure how that works for the highlighting. I 've chosen not to use typescript because I can't deal with all the error messages. I kinda want to limit the number of things I'm trying to learn at one time. Solid and Rust are enough with all the other libraries associated.
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
or
jsx is fine too
jsx is fine too
jsx const because_like_this = 'it looks better'; return <div/> ``` at least on desktop
d34dbug
d34dbugā€¢5mo ago
gotcha, so you just add the tsx or jsx after the ```?
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
exactly
d34dbug
d34dbugā€¢5mo ago
ok, not done that before. Cool!
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
just for sanity check: can you do
async (e) => {
e.preventDefault();
const session = sessionSelected()
if(session){
console.log(session)
await set_session({session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
async (e) => {
e.preventDefault();
const session = sessionSelected()
if(session){
console.log(session)
await set_session({session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
d34dbug
d34dbugā€¢5mo ago
Odd! That seems to be working. I'll do some more testing to make sure, but weird. I'm very curious why that would change anything functionally.
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
what does
async (e) => {
e.preventDefault();
if(sessionSelected()){
console.log(sessionSelected())
await set_session({sessionSelected()});
console.log(sessionSelected())
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
async (e) => {
e.preventDefault();
if(sessionSelected()){
console.log(sessionSelected())
await set_session({sessionSelected()});
console.log(sessionSelected())
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
this log?
d34dbug
d34dbugā€¢5mo ago
It logs the correct Id, but it fails to be reactive - i.e. the parent component is not rendered. I did however have to remove the {} from:
await set_session({sessionSelected()});
await set_session({sessionSelected()});
Because I was getting the error that a signature could only be used in tsx, or something like that
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
a ye lol typo should have been await set_session({id:sessionSelected()}); or whatever u had before i guess there was a typo here too:
async (e) => {
e.preventDefault();
const session = sessionSelected()
if(session){
console.log(session)
await set_session({id: session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
async (e) => {
e.preventDefault();
const session = sessionSelected()
if(session){
console.log(session)
await set_session({id: session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}
d34dbug
d34dbugā€¢5mo ago
current that doesn't work:
<button
id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
await set_session({id:sessionSelected()});
console.log(sessionSelected())
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
<button
id="but_sel"
onClick={async (e) => {
e.preventDefault();
if(sessionSelected()){
await set_session({id:sessionSelected()});
console.log(sessionSelected())
props.setActiveSession(sessionSelected());
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
this does seem to work:
<button
id="but_sel"
onClick={async (e) => {
e.preventDefault();
let session = sessionSelected();
if(session){
await set_session({id:session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
<button
id="but_sel"
onClick={async (e) => {
e.preventDefault();
let session = sessionSelected();
if(session){
await set_session({id:session});
console.log(session)
props.setActiveSession(session);
props.setSection(undefined);
}else{
await message("please choose a session");
}
}}
>
the only difference seems to be that the call to the signal getter is happening inside the await in my initial code. It's also called repeatedly, but that doesn't seem likely to be an issue. If the problem is that the signal getter is called inside the await, that might warrant a deeper dive into the reason or maybe an informative post indicating that this shouldn't be done (calling the getter inside an await)
Brendan
Brendanā€¢5mo ago
Calling the getter after await should be fine as this is just an event handler (not an effect or memo).
What you describe suggests that the value of sessionSelected() is changing between when that click handler starts and when the async server call completes. Are you sure there isn't something else setting that signal in the meantime? The safe option is probably capturing the value at the start of the handler - like the second code sample above is doing. That way you know you are using the same value all the way through.
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
they mention
It logs the correct Id, but it fails to be reactive - i.e. the parent component is not rendered.
@d34dbug if possible could u make a reproduction of it in the solid playground?
d34dbug
d34dbugā€¢5mo ago
I'm not sure as I won't have time til Monday at the earliest and I'll have to figure out how to simulate a basic backend behavior. I'll see what I can do. šŸ˜¦ Looks like I'm not going to be able to at the moment. Turns out I got sick and it put me out of commission for several days. I'm just too way behind on where I'd like to be on my project now. Sorry.
bigmistqke šŸŒˆ
bigmistqke šŸŒˆā€¢5mo ago
I am sorry to hear! Hope you feel better soon!
d34dbug
d34dbugā€¢5mo ago
Thank you. I am feeling much better than I was, but I am so behind.