How to use the custom hook useCustomHook() in Next.js and prevent the did not match server/client error without using useEffect()? Like when using swr for example.
useData() stores data on the client side (context + localStorage).
I am trying to create a static site with some data provided by the user.
function useCustomHook() {
const [{ data }, dispatch] = useData()
if (typeof window !== 'undefined') { // Client side
return { data: data }
}
return { data: undefined }
}
export default function Page() {
const { data } = useCustomHook()
if (!data) {
return <div>No data...</div>
}
return <div>Data {data.foobar}</div>
}
Context provider (<DataProvider> @ _app.js)
import { useReducer, useContext, createContext } from 'react'
const DataStateContext = createContext()
const initialState = {
data: {},
}
const reducer = (state, action) => {
switch (action.type) {
default:
throw new Error(`Unknown action: ${action.type}`)
}
}
export const DataProvider = ({ children }) => {
const localState = initialState
// Get the data from localStorage
try {
localState.data = localStorage.getItem('data')
? JSON.parse(localStorage.getItem('data'))
: null
} catch (err) {}
const [state, dispatch] = useReducer(reducer, localState)
return (
<DataStateContext.Provider value={[state, dispatch]}>
{children}
</DataStateContext.Provider>
)
}
export const useData = () => useContext(DataStateContext)
Will result in Warning: Text content did not match. Server: "No data..." Client: "Data " when I reload the page.
But when I use useSWR I can reload the page without getting an error. Also the request is done only on the client side, server side data is just undefined (server doesn't make a request at all). How does this work? I have checked the code from swr, but I don't get it.
import useSWR from "swr";
const fetcher = (url) => fetch(url).then((res) => res.json());
export default function App() {
const { data, error } = useSWR(
"https://api.github.com/repos/vercel/swr",
fetcher
);
if (error) return "An error has occurred.";
if (!data) return "Loading...";
return (
<div>{data.description}</div>
);
}