S
SolidJS•6mo ago
aws

Best way how to call sever function onClick (SOLVED)

Hi iam just playing with solid but still cant find best way how to call server side action from simple onClick. I can use API url to call it there i can prepare data and return them. But i think there must be something better?
13 Replies
brenelz
brenelz•6mo ago
Are you talking about a server function or a server action? A server action you add to a form like <form action={some FormAction}
aws
aws•6mo ago
Hi thanks for reply basically what i need to do is <button onClick={onClickHandler}>fetch</button> const onClickHandler = () => { //call server function that returns signed request parameters // setStore(createResource(parametersFromServerFunction, async() => {await fetch ....}) } something like this. since iam on router 0.8.5 i dont have actions available when i try updat to 0.10.5 I get TypeError: Comp is not a function my dependencies "dependencies": { "@solidjs/meta": "^0.29.3", "@solidjs/router": "^0.10.5", "solid-js": "^1.8.7", "solid-start": "^0.3.10" } } i tried every single approach but still cant make this work awww i used really old solidjs start 😦
brenelz
brenelz•6mo ago
yeah solid-start 0.4 changes a bunch of stuff
apollo79
apollo79•6mo ago
I think the new router (v0.10.x) is not compatible with solid-start v0.3.x If you want to use it you'll have to upgrade to 0.4.x
aws
aws•6mo ago
yes router 0.4.x makes things really easy and straight forward
brenelz
brenelz•6mo ago
So you got things figured out?
aws
aws•6mo ago
olk giving this up will try qwik if there is better doc or will make esy api routes. simple thing how to get data from server when i need it. page load / click button.
import {createAsync} from "@solidjs/router";
import {Show} from "solid-js";
import "tailwindcss/tailwind.css";
import {signRequestT} from "~/api/sign";
import "./index.css";

export default function Home() {

const getSign = createAsync(signRequestT);


return (
<Show when={!!getSign()}>
<main>
<title class="font-rs">TEST {getSign()}</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">TEST</div>
<div id="main" class="flex flex-nowrap">
</div>
</main>
</Show>
);
}
import {createAsync} from "@solidjs/router";
import {Show} from "solid-js";
import "tailwindcss/tailwind.css";
import {signRequestT} from "~/api/sign";
import "./index.css";

export default function Home() {

const getSign = createAsync(signRequestT);


return (
<Show when={!!getSign()}>
<main>
<title class="font-rs">TEST {getSign()}</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">TEST</div>
<div id="main" class="flex flex-nowrap">
</div>
</main>
</Show>
);
}
"user server";
export const signRequestT = async () => {
console.log("AA");
return Date.now().toString();

};
// in real application the should be
// export const signRequest = (data: any) => {
// return crypto.createSign("sha512").update(Buffer.from(data)).end().sign(readKeys().privateKey).toString("base64");
// };
// where readkeys need to be performed only on server.
"user server";
export const signRequestT = async () => {
console.log("AA");
return Date.now().toString();

};
// in real application the should be
// export const signRequest = (data: any) => {
// return crypto.createSign("sha512").update(Buffer.from(data)).end().sign(readKeys().privateKey).toString("base64");
// };
// where readkeys need to be performed only on server.
this gives me "AA" output server / client and console error caught (in promise) Error: Hydration Mismatch. Unable to find DOM nodes for hydration key: 0-0-0-0-0-0-0-1-0-0-0-0-0-0-0-0-0-4-0 @brenelz
brenelz
brenelz•6mo ago
it should be "use server" instead of "user server"
aws
aws•6mo ago
f......... so stupid misstake
import {Params, action, createAsync, useAction, useSearchParams} from "@solidjs/router";
import {Show, createComputed, createSignal} from "solid-js";
import "tailwindcss/tailwind.css";
import {Photo, getPhotos} from "~/api/photos-api";
import {signRequest} from "~/api/sign";
import "./index.css";

const createAsyncFactory = (params: Params) => createAsync(async () => {
const dt = Date.now() + 30000;
const p = {page: params.page ?? 1, date: dt.toString()};
const sign = await useAction(action(signRequest))(JSON.stringify(p));
const requestParams = new URLSearchParams({...p, sign});
return getPhotos(requestParams.toString());
});

export default function Home() {

const [params] = useSearchParams();
const [s,setS] = createSignal<Photo[] | undefined>(undefined);
const [c,setC] = createSignal<boolean>(false);
setS(createAsyncFactory(params));

createComputed(() => {
!!c() ? setS(createAsyncFactory(params)) : setC(false);
setC(false);
});
console.log(s());
return (
<Show when={s()}>
<main>
<button onClick={() => setC(true)}>AA</button>
<title class="font-rs">TEST</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">TEST {s()?.length}</div>
<div id="main" class="flex flex-nowrap">
</div>
</main>
</Show>
);
}
import {Params, action, createAsync, useAction, useSearchParams} from "@solidjs/router";
import {Show, createComputed, createSignal} from "solid-js";
import "tailwindcss/tailwind.css";
import {Photo, getPhotos} from "~/api/photos-api";
import {signRequest} from "~/api/sign";
import "./index.css";

const createAsyncFactory = (params: Params) => createAsync(async () => {
const dt = Date.now() + 30000;
const p = {page: params.page ?? 1, date: dt.toString()};
const sign = await useAction(action(signRequest))(JSON.stringify(p));
const requestParams = new URLSearchParams({...p, sign});
return getPhotos(requestParams.toString());
});

export default function Home() {

const [params] = useSearchParams();
const [s,setS] = createSignal<Photo[] | undefined>(undefined);
const [c,setC] = createSignal<boolean>(false);
setS(createAsyncFactory(params));

createComputed(() => {
!!c() ? setS(createAsyncFactory(params)) : setC(false);
setC(false);
});
console.log(s());
return (
<Show when={s()}>
<main>
<button onClick={() => setC(true)}>AA</button>
<title class="font-rs">TEST</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">TEST {s()?.length}</div>
<div id="main" class="flex flex-nowrap">
</div>
</main>
</Show>
);
}
Last attempt All works nice but when i hit button AA i can see i send request it returns right data but s signal is undefined. thanks for helping
brenelz
brenelz•6mo ago
Return value from createAsync is already a signal I think
aws
aws•6mo ago
yes but when i want refresh / call load more items on click i need mutate this signal. and yes its accessor
Brendonovich
Brendonovich•6mo ago
Can't this be done much more simply just using createResource and calling the server function directly, ignoring the action apis since you're not doing a form submission or anything?
export default function Home() {
const [searchParams] = useSearchParams();

const [photos, photosActions] = createResource(
() => ({ page: searchParams.page }),
async ({ page }) => {
const dt = Date.now() + 30000;
const p = { page: page ?? 1, date: dt.toString() };

const sign = await signRequest(JSON.stringify(p));
const requestParams = new URLSearchParams({ ...p, sign });

return await getPhotos(requestParams.toString());
},
);

return (
<Show when={photos()}>
{(photos) => (
<main>
<button onClick={() => photosActions.refetch()}>Refetch</button>
<title class="font-rs">TEST</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">
Photos Count: {photos().length}
</div>
<div id="main" class="flex flex-nowrap" />
</main>
)}
</Show>
);
}
export default function Home() {
const [searchParams] = useSearchParams();

const [photos, photosActions] = createResource(
() => ({ page: searchParams.page }),
async ({ page }) => {
const dt = Date.now() + 30000;
const p = { page: page ?? 1, date: dt.toString() };

const sign = await signRequest(JSON.stringify(p));
const requestParams = new URLSearchParams({ ...p, sign });

return await getPhotos(requestParams.toString());
},
);

return (
<Show when={photos()}>
{(photos) => (
<main>
<button onClick={() => photosActions.refetch()}>Refetch</button>
<title class="font-rs">TEST</title>
<div class="content-center text-center font-rs text-slate-500 text-2xl">
Photos Count: {photos().length}
</div>
<div id="main" class="flex flex-nowrap" />
</main>
)}
</Show>
);
}
aws
aws•6mo ago
^^^ yes this is it . dont realized i can call fucntion directly from resource. But what i missed is REFRESH !!! function thats the big one. Thanks againg for helping.