Je Suis Un Ami
Je Suis Un Ami
Explore posts from servers
SSolidJS
Created by Je Suis Un Ami on 6/3/2024 in #support
How to Execute Server Action on Each Route Visit?
I have a home component (code in comments) In summary, what this component does is it calls a server action to check if the user is authenticated. If the user is authenticated, it redirects the user to the dashboard route. Otherwise, it redirects the user to the login route. Now, here's my question. What I want to do is perform this verification every time the home route is visited (even from a client-side redirect). From my logs however, it doesn't look like the server action is being called in subsequent visits to this route (i.e. after the account setup process is complete. The reason I know this is because "Executing checks to determine redirect" is being printed on my console. But, none of the other logs that would be printed if the action completed are. In other words authenticatedUser.result is always falsy. How would I go about doing what I am trying to do? Is there a different approach I should be taking to accomplish what I am trying to do? Thanks. Like I said, component code is in the first comment of this thread.
16 replies
SSolidJS
Created by Je Suis Un Ami on 5/2/2024 in #support
Server Actions and Cookies sending error: Cannot set headers after they are sent to the clien
Maybe I am misunderstanding something here. I am following the docs for Actions. Basically, what this component is supposed to do is check for the pressence of a session cookie. And, if the user is authenticated, redirects the client to the dashboard page. And if not, it redirects the client to the login page.
export default function Home() {
const loadAuthenticatedUser = useAction(getAuthenticatedUserAction);
const navigate = useNavigate();
loadAuthenticatedUser();
const authenticatedUser = useSubmission(getAuthenticatedUserAction);
const [_, { setUser, clearUser }] = useUserContext();
const [serverError, setServerError] = createSignal("");

createEffect(() => {
if (authenticatedUser.result) {
// If the user is authenticated, we redirect them to the dashboard page.
// otherwise, we show them the main page.
const result = authenticatedUser.result;
if (result.success) {
setUser(result.data as User);
navigate("/dashboard");
} else {
if (result.data instanceof AppException) {
setServerError(result.message);
} else {
// for now, we ust redirect them to the login page. as soon as we get more traction,
// we will have a proper home page deidicated for marketing.
clearUser();
navigate("/login");
}
}
authenticatedUser.clear();
}
});

const handleRetry = () => {
setServerError("");
authenticatedUser.retry();
};

return (
<Show
when={!serverError()}
fallback={
<ConfirmationMessage
title="Something went wrong."
description={serverError()}
buttonText="Try Again"
onClick={handleRetry}
image="img/logo.svg"
/>
}
>
<></>
</Show>
);
}
export default function Home() {
const loadAuthenticatedUser = useAction(getAuthenticatedUserAction);
const navigate = useNavigate();
loadAuthenticatedUser();
const authenticatedUser = useSubmission(getAuthenticatedUserAction);
const [_, { setUser, clearUser }] = useUserContext();
const [serverError, setServerError] = createSignal("");

createEffect(() => {
if (authenticatedUser.result) {
// If the user is authenticated, we redirect them to the dashboard page.
// otherwise, we show them the main page.
const result = authenticatedUser.result;
if (result.success) {
setUser(result.data as User);
navigate("/dashboard");
} else {
if (result.data instanceof AppException) {
setServerError(result.message);
} else {
// for now, we ust redirect them to the login page. as soon as we get more traction,
// we will have a proper home page deidicated for marketing.
clearUser();
navigate("/login");
}
}
authenticatedUser.clear();
}
});

const handleRetry = () => {
setServerError("");
authenticatedUser.retry();
};

return (
<Show
when={!serverError()}
fallback={
<ConfirmationMessage
title="Something went wrong."
description={serverError()}
buttonText="Try Again"
onClick={handleRetry}
image="img/logo.svg"
/>
}
>
<></>
</Show>
);
}
I included the action definition in the comments.
29 replies
SSolidJS
Created by Je Suis Un Ami on 4/23/2024 in #support
Hydration Mismatch Error Every Time I Update a Component
No description
3 replies
SSolidJS
Created by Je Suis Un Ami on 3/17/2024 in #support
Dynamic Route Being Called Twice
No description
2 replies
SSolidJS
Created by Je Suis Un Ami on 8/30/2023 in #support
Context Not Being Defined
I am running into a problem where the AuthContext isn't being defined in m app. Here's my App component:
const App: Component = () => {
console.log("Rendering App Component");
return (
<MetaProvider>
<Title>{siteName}</Title>
<AuthProvider>
<Main />
</AuthProvider>
</MetaProvider>
);
};
const App: Component = () => {
console.log("Rendering App Component");
return (
<MetaProvider>
<Title>{siteName}</Title>
<AuthProvider>
<Main />
</AuthProvider>
</MetaProvider>
);
};
For convenience, here is my <mAIN /> component:
const Main: Component = () => {
console.log("Rendering main");
const [_, authenticated] = useAuthContext();
console.log(`Authenticated: ${authenticated()}`);
const Content = useRoutes(routes);
return (
<Router>
<div class="h-full bg-white">
<Show
when={authenticated()}
fallback={
<DefaultLayout>
<Content />
</DefaultLayout>
}
>
<ProfileProvider>
<EnsureClientSetup>
<AppProvider>
<DashboardLayout>
<Content />
</DashboardLayout>
</AppProvider>
</EnsureClientSetup>
</ProfileProvider>
</Show>
</div>
</Router>
);
};
const Main: Component = () => {
console.log("Rendering main");
const [_, authenticated] = useAuthContext();
console.log(`Authenticated: ${authenticated()}`);
const Content = useRoutes(routes);
return (
<Router>
<div class="h-full bg-white">
<Show
when={authenticated()}
fallback={
<DefaultLayout>
<Content />
</DefaultLayout>
}
>
<ProfileProvider>
<EnsureClientSetup>
<AppProvider>
<DashboardLayout>
<Content />
</DashboardLayout>
</AppProvider>
</EnsureClientSetup>
</ProfileProvider>
</Show>
</div>
</Router>
);
};
Essentially, the error being thrown is Uncaught TypeError: Cannot read properties of null, referring to the auth check being done by the authenticated() signal, defined in the AuthContext context. Here is the slimmed down version of my AuthContext:
export const AuthProvider: ParentComponent = (props) => {
console.log("Defining Auth Provider");
// ... more code here

<ErrorBoundary
fallback={(error: Error) => (
<DefaultLayout>
<span>
<AppError error={error} onRetry={refresh} />
</span>
</DefaultLayout>
)}
>
<Suspense>
<AuthContext.Provider
value={[
auth,
isAuthenticated,
{
authenticate: authenticate,
refreshAuth: refresh,
unauthenticate: unauthenticate,
},
]}
>
{props.children}
</AuthContext.Provider>
</Suspense>
</ErrorBoundary>
);
}

export const useAuthContext = () => {
return useContext(AuthContext)!;
};
export const AuthProvider: ParentComponent = (props) => {
console.log("Defining Auth Provider");
// ... more code here

<ErrorBoundary
fallback={(error: Error) => (
<DefaultLayout>
<span>
<AppError error={error} onRetry={refresh} />
</span>
</DefaultLayout>
)}
>
<Suspense>
<AuthContext.Provider
value={[
auth,
isAuthenticated,
{
authenticate: authenticate,
refreshAuth: refresh,
unauthenticate: unauthenticate,
},
]}
>
{props.children}
</AuthContext.Provider>
</Suspense>
</ErrorBoundary>
);
}

export const useAuthContext = () => {
return useContext(AuthContext)!;
};
In my logs, I know that AuthContext is not being defined because the print statement defined in it is never shown. How would I fix this?
2 replies
SSolidJS
Created by Je Suis Un Ami on 6/11/2023 in #support
Saving Results of routeData() into a Context
What is the proper way to save the results of routeData() into a context? So, here's my setup. Here's my root.
<Body class="bg-primary h-min w-screen">
<div class="text-center mx-auto text-spring pt-4 px-0 w-full">
<Suspense>
<ErrorBoundary>
<Navigation />
<IslandsProvider>
<Routes>
<FileRoutes />
</Routes>
</IslandsProvider>
<Footer />
</ErrorBoundary>
</Suspense>
<Scripts />
</div>
</Body>
<Body class="bg-primary h-min w-screen">
<div class="text-center mx-auto text-spring pt-4 px-0 w-full">
<Suspense>
<ErrorBoundary>
<Navigation />
<IslandsProvider>
<Routes>
<FileRoutes />
</Routes>
</IslandsProvider>
<Footer />
</ErrorBoundary>
</Suspense>
<Scripts />
</div>
</Body>
And, in my route component, I have it like this:
export function routeData() {
const resource = createRouteData(async () => await getLatestIslands());
console.log(resource());
return resource;
}

export default function Home() {
console.log("Defining index");
const islands = useRouteData<typeof routeData>();
console.log(islands());
const [_, addIslands] = useIslandsContext();
addIslands(islands()!);

return (
<main>
<FeaturedIsland />
<LatestIslands />
</main>
);
}
export function routeData() {
const resource = createRouteData(async () => await getLatestIslands());
console.log(resource());
return resource;
}

export default function Home() {
console.log("Defining index");
const islands = useRouteData<typeof routeData>();
console.log(islands());
const [_, addIslands] = useIslandsContext();
addIslands(islands()!);

return (
<main>
<FeaturedIsland />
<LatestIslands />
</main>
);
}
According to my logs, data is present in both the routeData() and when the component initially renders. However, it doesn't seem like it is ever put into the context (as in, it's saying it is undefined on my UI). How would I go about this?
2 replies
SSolidJS
Created by Je Suis Un Ami on 5/4/2023 in #support
props.children is not defined.
I have this component.
const AuthProvider: Component<AuthContextProps> = (props) => {
/// the local store.
const [tokenStorage, setTokenStorage] = createLocalStorage({
api: localStorage,
prefix: "vista-auth-",
deserializer: (data) => {
if (!data || data == "undefined") {
return "";
}
return data;
},
serializer: (value, key, options) => {
return value;
},
});
const [auth, setAuth] = createStore({
access: tokenStorage.access,
refresh: tokenStorage.refresh,
get authenticated(): boolean {
const hasAccess = this.access.length > 0;
const hasRefresh = this.refresh.length > 0;
return hasAccess || hasRefresh;
},
} as AuthState);

return (
<AuthContext.Provider value={auth}>
{props.children!}
</AuthContext.Provider>
);
};
const AuthProvider: Component<AuthContextProps> = (props) => {
/// the local store.
const [tokenStorage, setTokenStorage] = createLocalStorage({
api: localStorage,
prefix: "vista-auth-",
deserializer: (data) => {
if (!data || data == "undefined") {
return "";
}
return data;
},
serializer: (value, key, options) => {
return value;
},
});
const [auth, setAuth] = createStore({
access: tokenStorage.access,
refresh: tokenStorage.refresh,
get authenticated(): boolean {
const hasAccess = this.access.length > 0;
const hasRefresh = this.refresh.length > 0;
return hasAccess || hasRefresh;
},
} as AuthState);

return (
<AuthContext.Provider value={auth}>
{props.children!}
</AuthContext.Provider>
);
};
My IDE is telling me that props.children isn't defined somehow. I'm guessing this is just some typing problem? How would I fix this?
8 replies
SSolidJS
Created by Je Suis Un Ami on 4/22/2023 in #support
Creating an Observable from a store.
Is there a way I can create an observable from a store? Essentially, what I want to do this:
import { observable } from “solid-js”;
import { createStore } from “solid-js/store”;
import { tap, map } from “RxJS/operators”;
import {from } from “RxJS”;

Interface AuthTokens {
access: string;
refresh: string;
}

const [tokens, setTokens] = createStore<AuthTokens>({});

const tokens$ = observable(tokens).pipe(
tap(value => //save to storage),
map(tokens => {
return from(fetch(…)).pipe(…)
})
)
import { observable } from “solid-js”;
import { createStore } from “solid-js/store”;
import { tap, map } from “RxJS/operators”;
import {from } from “RxJS”;

Interface AuthTokens {
access: string;
refresh: string;
}

const [tokens, setTokens] = createStore<AuthTokens>({});

const tokens$ = observable(tokens).pipe(
tap(value => //save to storage),
map(tokens => {
return from(fetch(…)).pipe(…)
})
)
Or, something like that at least. This fails because the observable() function accepts an Accessor, which pretty much is only signals. Is there a way I can make it work with stores as well?
4 replies