T
TanStack4mo ago
fascinating-indigo

how to run something before content is shown?

Is there a way to run some code that can throw a redirect before a page is shown? I tried with the beforeload but its triggering on hover, i need when entering the page (before effects in page run) to trigger a redirect in some scenarios, is that possible? i also tried onEnter but it executes before the effects, i need something like a beforeEnter i think
25 Replies
like-gold
like-gold4mo ago
sounds like beforeLoad is perfect for this why is this not working for you? please provide a complete minimal example, ideally by forking one of the existing router examples on stackblitz
fascinating-indigo
fascinating-indigoOP4mo ago
because beforeLoad runs on hover, i want to keep that behaviour, and only throw a redirect on enter if user is not logged in, is that possible?
like-gold
like-gold4mo ago
why is the running on hover an issue? the redirect in a preload upon hover wont affect your current rendered route
fascinating-indigo
fascinating-indigoOP4mo ago
oh i didnt realize that sorry thanks manuel!
like-gold
like-gold4mo ago
just try it out the preload follows the redirect so essentially it preloads the target route
fascinating-indigo
fascinating-indigoOP4mo ago
the loader is running in the background, thats the problem i was having, is there a way to ensure it only runs in the frontend?
like-gold
like-gold4mo ago
not sure what you mean background? frontend?
fascinating-indigo
fascinating-indigoOP4mo ago
backend sorry
like-gold
like-gold4mo ago
so are you using just router or start here?
fascinating-indigo
fascinating-indigoOP4mo ago
start alpha
like-gold
like-gold4mo ago
ok, so how does the link hover matter?
fascinating-indigo
fascinating-indigoOP4mo ago
sorry i was wrong about the link hover, after that change the problem im having now is that if i reload the page in that route the loader runs in the backend, and i cant validate the user data there, is there a way to only run it in the front only? i have stale time set to 0, i understand this should make the loader run in both places? or run it in both places, that also works for me
like-gold
like-gold4mo ago
why cant you validate the user data in the backend? i also dont see how the beforeLoad throwing a redirect has anything to do with a loader running on the server
fascinating-indigo
fascinating-indigoOP4mo ago
the responses from tasntack start will be cached in a cdn, so i cant respond with any user specific data in my setup the problems are not related, originally i thought there was a problem with throwing the redirect with the hover, but since you explained that it wont affect the hover i made the change and now im experiencing the other problem, of the loader running only in the backend when i reload the page
like-gold
like-gold4mo ago
ah ok i thought this was somehow related
fascinating-indigo
fascinating-indigoOP4mo ago
sorry if i mixed that up
like-gold
like-gold4mo ago
why are the responses cached though?
like-gold
like-gold4mo ago
GitHub
[RFC] SPA Mode Enhancements · TanStack router · Discussion #3394
TanStack Start is a unique opportunity for SPAs to have server-side features, but may come with some decisions to make. What does SPA mode mean? From my perspective, SPA mode is a general term for ...
fascinating-indigo
fascinating-indigoOP4mo ago
i can cache all pages or none, so because of performance reasons and because most pages dont require login i cache the response in a cdn, but some routes requires the user to be logged in, for those routes i still want to keep ssr because some parts of the app like header or footer should be visible while the profile is loading Also if the loaded data from the router has stale time of 0 (defaultPreloadStaleTime), shouldnt this be revalidated (loader triggered again) in the frontend? or im not understanding that correctly?
like-gold
like-gold4mo ago
not upon hydration in start, loaders run on the server during SSR and then on subsequent client navigations, they run on the client which is why I linked to the SPA mode above, which will allow you to only run a loader on the client
fascinating-indigo
fascinating-indigoOP4mo ago
but with spa mode i loose ssr and i have too many pages to do prerendering to static html files, doing ssr also allows the pages from being re-generated every N hours (cdn cache duration) so in start there isnt a way to run something on the client on first page load for a route then? i also want to keep the ssr for the logged in required pages to show the header and loading shell while the profile is being fetch
like-gold
like-gold4mo ago
but what are you SSRing then? if you dont have the loader data?
fascinating-indigo
fascinating-indigoOP4mo ago
i have other loaders in parent routes that show the categories in the header for example, these loaders dont require login
like-gold
like-gold4mo ago
SPA mode will also allow you to set ssr: false to a (sub)route and then the loaders will not run the server but only on the client until we have that implemented, you might just use useQuery in that specific route component then it gets only executed on the client wont benefit from link prefetching though you could of course conditionally run ensureQueryData in the loader depending on whether the loader runs on client or server or let createIsormophicFn handle that for you
yelping-magenta
yelping-magenta2w ago
So am doing something like this
//isomorphic pocketbase instance
import { TypedPocketBase } from "@tigawanna/typed-pocketbase";
import { Schema } from "../types/pb-types";
import { browserPb } from "./browser-client";
import { createIsomorphicFn } from "@tanstack/react-start";
import { getCookie } from "@tanstack/react-start/server";

export const $isomorphicePocketbase = createIsomorphicFn()
.client(() => {
// a global instance meant to be shared on the cllient side
return browserPb;
})
.server(() => {
// a fresh instance with the authstore initialized from cookies per request
const url = process.env.VITE_PB_URL;
if (!url) {
throw new Error("Pocketbase API url not defined !");
}
const client = new TypedPocketBase<Schema>(url);
const authCookie = getCookie("pb_auth");
if (authCookie) {
// loadFromCookie expects a cookie string like "pb_auth=<value>"
client.authStore.loadFromCookie(`pb_auth=${authCookie}`);
}
return client;
});
//isomorphic pocketbase instance
import { TypedPocketBase } from "@tigawanna/typed-pocketbase";
import { Schema } from "../types/pb-types";
import { browserPb } from "./browser-client";
import { createIsomorphicFn } from "@tanstack/react-start";
import { getCookie } from "@tanstack/react-start/server";

export const $isomorphicePocketbase = createIsomorphicFn()
.client(() => {
// a global instance meant to be shared on the cllient side
return browserPb;
})
.server(() => {
// a fresh instance with the authstore initialized from cookies per request
const url = process.env.VITE_PB_URL;
if (!url) {
throw new Error("Pocketbase API url not defined !");
}
const client = new TypedPocketBase<Schema>(url);
const authCookie = getCookie("pb_auth");
if (authCookie) {
// loadFromCookie expects a cookie string like "pb_auth=<value>"
client.authStore.loadFromCookie(`pb_auth=${authCookie}`);
}
return client;
});
and then using it to instantiate the router context
import { createRouter as createTanstackRouter } from "@tanstack/react-router";
import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
import * as TanstackQuery from "./integrations/tanstack-query/root-provider";
import { routeTree } from "./routeTree.gen";
import { $isomorphicePocketbase } from "./lib/pocketbase/clients/ts-router--pocketbase";


// Create a new router instance
export const createRouter = () => {
const rqContext = TanstackQuery.getContext();

const router = createTanstackRouter({
routeTree,
context: { ...rqContext, pb: $isomorphicePocketbase() },
defaultPreload: "intent",
Wrap: (props: { children: React.ReactNode }) => {
return <TanstackQuery.Provider {...rqContext}>{props.children}</TanstackQuery.Provider>;
},
});
setupRouterSsrQueryIntegration({ router, queryClient: rqContext.queryClient });

return router;
};

// Register the router instance for type safety
declare module "@tanstack/react-router" {
interface Register {
router: ReturnType<typeof createRouter>;
}
}
import { createRouter as createTanstackRouter } from "@tanstack/react-router";
import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
import * as TanstackQuery from "./integrations/tanstack-query/root-provider";
import { routeTree } from "./routeTree.gen";
import { $isomorphicePocketbase } from "./lib/pocketbase/clients/ts-router--pocketbase";


// Create a new router instance
export const createRouter = () => {
const rqContext = TanstackQuery.getContext();

const router = createTanstackRouter({
routeTree,
context: { ...rqContext, pb: $isomorphicePocketbase() },
defaultPreload: "intent",
Wrap: (props: { children: React.ReactNode }) => {
return <TanstackQuery.Provider {...rqContext}>{props.children}</TanstackQuery.Provider>;
},
});
setupRouterSsrQueryIntegration({ router, queryClient: rqContext.queryClient });

return router;
};

// Register the router instance for type safety
declare module "@tanstack/react-router" {
interface Register {
router: ReturnType<typeof createRouter>;
}
}
and using it like this
export const Route = createFileRoute("/")({
component: App,
loader: async (ctx) => {
const properties = await ctx.context.pb.from("properties").getList(1,25)
return properties;
},
});

function App() {
const properties = Route.useLoaderData();
return (
<ResponsiveGenericToolbar>
<div className="flex h-full min-h-screen w-full flex-col items-center justify-center">
<h3>Welcome Home!!!</h3>
{properties.items.map((property) => (
<div key={property.id} className="p-4 border rounded-lg m-2">
<h4>{property.title}</h4>
<p>{property.description}</p>
</div>
))}
</div>
</ResponsiveGenericToolbar>
);
}
export const Route = createFileRoute("/")({
component: App,
loader: async (ctx) => {
const properties = await ctx.context.pb.from("properties").getList(1,25)
return properties;
},
});

function App() {
const properties = Route.useLoaderData();
return (
<ResponsiveGenericToolbar>
<div className="flex h-full min-h-screen w-full flex-col items-center justify-center">
<h3>Welcome Home!!!</h3>
{properties.items.map((property) => (
<div key={property.id} className="p-4 border rounded-lg m-2">
<h4>{property.title}</h4>
<p>{property.description}</p>
</div>
))}
</div>
</ResponsiveGenericToolbar>
);
}
so far so good no errors but am wondering if am makng an obyious mistakes?

Did you find this page helpful?