Best approach for using createResource

I have a question. The createResource should be used outside the component and not inside the component, is this a correct statement? I only ask because I noticed the fetcher runs twice if put inside a component vs having it outside the component?
2 Replies
mdynnl
mdynnl2mo ago
It's the opposite and if you're seeing this then something's wrong. Also here https://discord.com/channels/722131463138705510/1266679656329773117
Casacobra
Casacobra2mo ago
@mdynnl I think I know the issue... thanks for getting back to me! I have the following app.tsx
export default function App() {
return (
<>
<Router
root={(props) => (
<>
<MetaProvider>
<Title>Supaflags</Title>
<ColorModeScript storageType={storageManager.type} />
<ColorModeProvider storageManager={storageManager}>
<AuthProvider>
<FlagsProvider>
<AuthGuard>{props.children}</AuthGuard>
</FlagsProvider>
</AuthProvider>
</ColorModeProvider>
</MetaProvider>
</>
)}
>
<Route path="/" component={AuthLayout}>
<Route path={["/", "/flags"]} component={Flags} />
<Route path="/flags/:id" component={FlagDetails} />
<Route path="/settings" component={Settings} />
</Route>
<Route path="/auth" component={DefaultLayout}>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={Signup} />
</Route>
<FileRoutes />
</Router>
<Toaster />
</>
)
}
export default function App() {
return (
<>
<Router
root={(props) => (
<>
<MetaProvider>
<Title>Supaflags</Title>
<ColorModeScript storageType={storageManager.type} />
<ColorModeProvider storageManager={storageManager}>
<AuthProvider>
<FlagsProvider>
<AuthGuard>{props.children}</AuthGuard>
</FlagsProvider>
</AuthProvider>
</ColorModeProvider>
</MetaProvider>
</>
)}
>
<Route path="/" component={AuthLayout}>
<Route path={["/", "/flags"]} component={Flags} />
<Route path="/flags/:id" component={FlagDetails} />
<Route path="/settings" component={Settings} />
</Route>
<Route path="/auth" component={DefaultLayout}>
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={Signup} />
</Route>
<FileRoutes />
</Router>
<Toaster />
</>
)
}
Then I have an AuthGuard that basically checks whether you have an auth session or not. If you visit / and have no session it redirects you to the login page auth/login.tsx I think the problem here is, it automatically runs createResource on the / page first then directs you to auth/login.tsx when you then log in it then directs you back to / which runs this twice. This is the AuthGuard page:
export default function AuthGuard(props: ComponentProps<"div">) {
const navigate = useNavigate()
const location = useLocation<LocationState>()
const rootPathName = "/"
const loginPathName = "/auth/signin"
const [isLoading, setIsLoading] = createSignal(false)
const [initialPath, setInitialPath] = createSignal(location.pathname)

const checkSession = async () => {
setIsLoading(true)
const { data } = await supabase.auth.getSession()
const session = data?.session

if (!session) {
if (location.pathname !== loginPathName) {
setInitialPath(location.pathname)
setSession(null)
}
navigate(loginPathName, { replace: true, state: { from: initialPath() } })
} else {
const redirectTo = location.state?.from || rootPathName
if (location.pathname === loginPathName) {
navigate(redirectTo, { replace: true })
}
}

setIsLoading(false)
}

checkSession()

return (
<Show when={isLoading()} fallback={<>{props.children}</>}>
<LoadingLayout />
</Show>
)
}
export default function AuthGuard(props: ComponentProps<"div">) {
const navigate = useNavigate()
const location = useLocation<LocationState>()
const rootPathName = "/"
const loginPathName = "/auth/signin"
const [isLoading, setIsLoading] = createSignal(false)
const [initialPath, setInitialPath] = createSignal(location.pathname)

const checkSession = async () => {
setIsLoading(true)
const { data } = await supabase.auth.getSession()
const session = data?.session

if (!session) {
if (location.pathname !== loginPathName) {
setInitialPath(location.pathname)
setSession(null)
}
navigate(loginPathName, { replace: true, state: { from: initialPath() } })
} else {
const redirectTo = location.state?.from || rootPathName
if (location.pathname === loginPathName) {
navigate(redirectTo, { replace: true })
}
}

setIsLoading(false)
}

checkSession()

return (
<Show when={isLoading()} fallback={<>{props.children}</>}>
<LoadingLayout />
</Show>
)
}
I then made the index page in app.tsx lazy load the component for the index page that basically fetches the resource, this definitely doesn't run the fetcher twice and fixes the issue, but its not what i wanted. Do you see what the issue could be here by any chance?
Want results from more Discord servers?
Add your server