Reputation: 1056
I've implemented a client-side request inside useEffect() per the documentation, and it works great when navigating inside the app, but if I load the page directly, it fails to return any data. I've checked that the user object is present, but somehow, it still always returns an empty set instead of the expected set of objects.
Dependencies:
{
"dependencies": {
"@supabase/auth-helpers-nextjs": "^0.2.8",
"@supabase/auth-helpers-react": "^0.2.4",
"@supabase/supabase-js": "^1.35.7",
"@supabase/ui": "^0.36.5",
"next": "12.3.1",
"pocketbase": "^0.7.1",
"react": "17.0.2",
"react-dom": "17.0.2"
},
}
pages/projects.tsx
import {GetServerSideProps, InferGetServerSidePropsType, NextPage} from 'next';
import styles from '../styles/Home.module.css';
import Footer from '../components/Footer';
import Header from '../components/Header';
import Meta from '../components/Meta';
import {useEffect, useState} from 'react';
import Link from 'next/link';
import {supabaseClient, withPageAuth} from '@supabase/auth-helpers-nextjs';
export const getServerSideProps: GetServerSideProps = withPageAuth({redirectTo: '/auth'});
const Projects: NextPage = ({user}: InferGetServerSidePropsType<typeof getServerSideProps>) => {
const [projects, setProjects] = useState<object | null>(null); // todo: Project types
const [isLoading, setLoading] = useState<boolean>(false);
useEffect(() => {
// fixme: works when navigating within the app, but not when the page is loaded from scratch
async function loadData() {
console.log({user});
const {data} = await supabaseClient.from('projects').select();
setLoading(false);
setProjects(data);
}
setLoading(true);
// Only run query once user is logged in.
// todo: error handling
if (user) loadData().then(() => console.log('Projects loaded', projects));
}, [user]);
return (
<div className={styles.container}>
<Meta titlePrefix={`Projects`} description={'todo'}></Meta>
<Header user={user} />
<main className={styles.main}>
<h1 className={styles.title}>Prioritizr Projects</h1>
<br /><br />
<div className={styles.grid3}>
{!projects && isLoading && <p className={styles.description}>Loading projects...</p>}
{
// @ts-ignore - todo: Project types
projects && projects.map(p => (<Link href={`projects/${p.id}`} key={p.id}>
<a className={styles.card}>
<h2 className={styles.solo}>{p.name}</h2>
</a>
</Link>))
}
{/* todo: module logic for handling partially-filled final row */}
</div>
<div className={styles.grid}>
<Link href='/new'>
<a className={styles.card}>
<h2>New Project →</h2>
<p>Need to prioritize a new set of things? Create a new project to get started on your own or with your
team.</p>
</a>
</Link>
</div>
</main>
<Footer />
</div>
);
};
export default Projects;
Upvotes: 1
Views: 1182
Reputation:
You can check isLoading
state in addition to the user
result before, since both of these states need to be resolved before you can fetch the data.
Adding both to the useEffect
dependencies and to the if
check should be enough.
Upvotes: 1
Reputation: 1152
Since you're using SSR, I'd recommend you fetch the data server-side in getServerSideProps
like so:
export const getServerSideProps = withPageAuth({
redirectTo: '/',
async getServerSideProps(ctx) {
// Run queries with RLS on the server
const { data } = await supabaseClient.from('projects').select();
return { props: { data } };
}
});
Then you have the data available in your page props.
If you want to fetch the data client-side, you would have to use the useUser
hook to get the user. This hook will let you know when the user
is set on the client-side.
Upvotes: 0