Last active
January 7, 2024 16:22
-
-
Save spro/a4ccb681ba05abde9943fdfcd9bf497d to your computer and use it in GitHub Desktop.
Attempt at SSR with Recoil - setting initial atom values with Next.js getServerSideProps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {useEffect} from 'react' | |
import {RecoilRoot, useRecoilState, atom} from 'recoil' | |
// User data | |
const user1 = {username: 'joe', bio: "You will never see me, unless of course this example is totally broken."} | |
const user2 = {username: 'bob', bio: "I am the one true user."} | |
const user3 = {username: 'fred', bio: "Just kidding, make way for the new guy."} | |
// Recoil atom to store user. The default user is user1, but it will be | |
// replaced when the root state is initialized | |
const userState = atom({ | |
key: 'user', | |
default: user1 | |
}) | |
// Keep a reference to all atoms by key for initializeRecoilState | |
const all_atoms = { | |
user: userState | |
} | |
// Where the magic happens: Used by RecoilRoot to update atoms by key given an | |
// initial state object of the form {key: initial_value} | |
const initializeRecoilState = (initialRecoilState) => ({set}) => | |
Object.keys(initialRecoilState).map((key) => { | |
const value = initialRecoilState[key] | |
const atom = all_atoms[key] | |
set(atom, value) | |
}) | |
// Component to display user info | |
function User() { | |
const [user, setUser] = useRecoilState(userState) | |
// Show recoil is alive by setting to user3 after a bit | |
useEffect(() => | |
setTimeout(() => setUser(user3), 2000) | |
, []) | |
return <div> | |
<strong className='username'>{user.username}</strong> | |
<p className='bio'>{user.bio}</p> | |
</div> | |
} | |
// Faux SSR "loading" user2 into the initial state | |
export async function getServerSideProps() { | |
const initialRecoilState = { | |
user: user2 | |
} | |
console.log("Created initial Recoil state:", initialRecoilState) | |
return { | |
props: {initialRecoilState} | |
} | |
} | |
export default function Home({initialRecoilState={}}) { | |
console.log('Rendering with initial Recoil state:', initialRecoilState) | |
return ( | |
<RecoilRoot initializeState={initializeRecoilState(initialRecoilState)}> | |
<User /> | |
</RecoilRoot> | |
) | |
} |
@kesavamuthu You cannot set Recoil state on the server. Why do you need an atomFamily
for that particular case? It looks like you could pass you data to an atom
and then manipulate it with a selector
or selectorFamily
.
"use client" is required when we import Recoil Root. getServerSideProps does not work (not get called) in the client component. then how are we supposed to initialize a recoil atom to a prop provided by getServerSideProps function.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
const editorAtomFam = atomFamily({
key: "editor",
default: (params) => new DefaultValue({ content: params }),
});
function getServerSideProps(ctx) {
editorAtomFam("init").default = new DefaultValue({
content: "articles.openingContent",
});
}
I've used this solution to set default values but it's not working the atom is undefined always.