Search code examples
react-contextpreactfreshjs

Why does splitting component overwrite the final result?


I'm following the useContext tutorial for Preact with Fresh. At the return statement of the User() component, I add a letter before the context value:

import { createContext } from 'preact'
import { useContext } from 'preact/hooks'

const Username = createContext()

export default function App() {
  return (
    <Username.Provider value="value">
      <User />
    </Username.Provider>
  )
}

function User() {
  const username = useContext(Username)
  return <>U{username}</>
}

This returns Uvalue as expected.

I then split the component to a separate file. This is the new code:

routes/index.tsx

import { User } from "../islands/User.tsx";
import { createContext } from 'preact'

export const Username = createContext()

export function ContextProvider({children}) {
  return (
    <Username.Provider value="value">{children} 
    </Username.Provider>
  );
}

export default function App() {
  return (
    <ContextProvider>
      <User />
    </ContextProvider>
  )
}

islands/User.tsx

import { useContext } from 'preact/hooks';
import { Form1Context } from '../routes/index.tsx'

export function User() {
  const username = useContext(Form1Context); 
  return <>U{username}</>;
}

Then the page return Uvalue, but then quickly be overwritten by U.

I cannot explain this behavior. Do you know why is that?


Solution

  • Fresh maintainer here:

    Fresh currently doesn't support passing context values from the server to the client. In the given code snippet the context provider is created on the server in a route and the island accesses the context value. When the browser makes the HTML from the server interactive and boots up the islands then there is no context provider around that which means the default value is used. The default value for your context provider is undefined which renders to nothing. So once the HTML becomes interactive the <>U{username}</> will render as just U.

    It's on the roadmap to support passing context values from the server to the browser, but there is no timeline yet. See this feature request: https://github.com/denoland/fresh/issues/983