I have a next.js page to display a post, like a blog, and I use Link to move from a post to another. To show the proper post I use another component, something like this (note that I cut a lot of code for semplicity)
const Index: NextPage<PageProps> = (props) => {
const router = useRouter();
let post = props.post;
return (
<>
<Post post={post}/>
<Link href={`/post/${encodeURIComponent(props.next.id)}`} passHref={true}>
<a>next post</a>
</Link>
<Link href={`/post/${encodeURIComponent(props.previous.id)}`} passHref={true}>
<a>previous post</a>
</Link>
</>
);
};
export default Index;
export const getServerSideProps = async (context) => {
const session = await getSession(context);
const pid = context.params.pid;
let postManager = new PostManager();
let post = await postManager.getPost(pid);
let siblings = null;
if (post) {
siblings = await postManager.getSiblings(post);
}
return {
props: {
post: JSON.parse(JSON.stringify(post)),
next: (siblings && siblings.next) ? JSON.parse(JSON.stringify(siblings.next)) : null,
previous: (siblings && siblings.previous) ? JSON.parse(JSON.stringify(siblings.previous)) : null,
session: session,
}
};
};
what it is strange is that in the Post component seems like useState is not executed after the first time I load the page:
const Post = props => {
const [title, setTitle] = useState(props.post.title);
console.log(props.post.title);
console.log(title);
here when I load the page "directly" the two values are the same (which is fine). Then when I click on Link (in the page component), the second console.log is showing the value from the content I loaded directly.
This doesn't happen if I take off Link and I leave <a>, but of course using Link is faster so I'd prefer to use it.
How can I "force" useState to set the correct value every time props has changed?
Because you are staying on the same page with shallow routing the component is not freshly re-rendered but the props are updated. This is intended react/next behaviour.
Add to your Post component the following:
useEffect(() => {
setTitle(props.post.title);
}, [props]);
This will update the state when the props are updated. Let me know if you have any questions.