Since Geolocation
is a client-only service, we provide it to RuntimeClient
.
We add Geolocation.layer
to MainLayer
inside RuntimeClient
:
import { Geolocation } from "@effect/platform-browser";
import { Layer, ManagedRuntime } from "effect";
const MainLayer = Layer.mergeAll(Geolocation.layer);
export const RuntimeClient = ManagedRuntime.make(MainLayer);
Most services in
@effect/platform-browser
and other platform libraries already provide a valid layer implementation, like here withGeolocation.layer
.
With this we can now use RuntimeClient
to execute action
, since RuntimeClient
includes a valid implementation of Geolocation
.
Executing effects in client components
We can use useActionState
again to execute action
inside Location
:
useActionState
is not limited to server actions. It can be used to execute any asynchronous function.
export default function Location() {
const [location, getLocation, pending] = useActionState(
() => RuntimeClient.runPromise(action),
null
);
return (
<p>
Location:{" "}
{location !== null
? `${location.coords.latitude} ${location.coords.longitude}`
: "-"}
</p>
);
}
We then also add a button to trigger getLocation
(so we can avoid useEffect
😅):
export default function Location() {
const [location, getLocation, pending] = useActionState(
() => RuntimeClient.runPromise(action),
null
);
return (
<div>
<button disabled={pending} onClick={getLocation}>
Get Location
</button>
<p>
Location:{" "}
{location !== null
? `${location.coords.latitude} ${location.coords.longitude}`
: "-"}
</p>
</div>
);
}
Let's not forget to add Location
to index.tsx
:
export default async function HomePage() {
return (
<div>
<title>Index</title>
<Location />
{await RuntimeServer.runPromise(
main.pipe(
Effect.match({
onFailure: Match.valueTags({
ParseError: (error) => <span>ParseError</span>,
RequestError: (error) => <span>RequestError</span>,
ResponseError: (error) => <span>ResponseError</span>,
}),
onSuccess: (posts) => <Posts posts={posts} />,
})
)
)}
</div>
);
}
Clicking "Get Location" will now trigger getLocation
. Your browser will ask you for permission to access your location. When you click "Allow", the location will be displayed.
You can now appreciate the advantage of having a server and client runtimes. Each runtime contains services specific for the two environments.
This avoids most problems when handling the separation between server and client. It becomes impossible at compile time to execute client effects on the server, and vice versa.