2

I've been looking at the documentation and how to use it with Next.js SSR, however I'm still clueless on how to actually implement it because every way I can think of doesn't make any sense.

According to this SO thread setting initial data was as simple as passing initialData in the options. However in the current version that doesn't exist and has been replaced with SWRConfig, instead of passing the data you wrap everything in a SWRConfig and pass in fallbackData (which itself the name is dumb it's used as initial data, it's only fallback data initially).


However if SWRConfig was a server component things would be fine, I can have my layout.tsx be

import {SWRConfig} from "swr";
import {fetch_data} from "@/api/data";

export default async function Layout({
  children,
}:{
  children: React.ReactNode,
}) {
  const fallbackData = await fetch_data();
  return (
    <SWRConfig value={{fallbackData}}>
      {children}
    </SWRConfig>

  )
}

Then inside {children} there could be the node

import useSWR from "swr";

const get_data = async () => {...}

export default function Page() {
  const {data, mutate} useSWR('/api/data', get_data);

  //Use `data` that is initially set from SWRConfig
}

However, SWRConfig is a client component which means that it needs to receive the data from a server component to then set it as the fallbackData. Resulting in a public_layout.tsx component but client only that receives the data from the layout to set to the SWRConfig


'use client';
import { SWRConfig } from "swr";
import { type DataType } from "@/util/db";

export default function Layout({
  children,
  fallbackData,
}: {
  children: React.ReactNode,
  fallbackData: DataType[],
}) {
  return (
    <SWRConfig value={{fallbackData}}>
      {children}
    </SWRConfig>
  )
}

Then the layout.tsx just uses the PublicLayout component and passes the data

import {fetch_data} from "@/api/data";
import PublicLayout from './public_layout'

export default async function Layout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <PublicLayout fallbackData={await fetch_data()}>
      {children}
    </PublicLayout>
  )
}

Then finally it can be used, same code as Page() above.


This can't actually be the correct way to do things right?

  • If it is the correct way, is there a cleaner and less confusing to set it up?
  • If it is the wrong way, what am I meant to be doing?

Also how do I pronounce "SWR"? I've been pronouncing it "sewer"

Zed
  • 651
  • 1
  • 5
  • 25
dontfknow
  • 155
  • 8

1 Answers1

0

I ended up not going with SWR because it was a pain to connect it with RxJS so I just did it manually and I've still got the optimistic UI that I wanted.

const add_item = async (current:DataType[], new_item:DataType) => {
  //Add item and get result which is the data
  //Return data if it got it
  //Return current if it fails
} 

export default function Page({
  default_data
}: {
  default_data:DataType[] 
}) {
  const [data, setData] = useState(default_data);

  return ( //Really basic example, this would want to not have hard coded values
    <button onClick={
      const new_item = { key:"just a test bro", text:"I wanted to be the key" };
      const optimistic = [...data, new_item];
      setData(optimistic);
      setData(await add_item(data, new_item));
    }>Testing</button>
  )
  
}

It's laid out in a much nicer way and with this I can add in RxJS support and debounce requests and make changes in batches

dontfknow
  • 155
  • 8