Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rendering hours from datetime breaks styled components #3645

Closed
alexalexyang opened this issue Jul 2, 2022 · 7 comments · May be fixed by ragrawal1234/remix#2
Closed

Rendering hours from datetime breaks styled components #3645

alexalexyang opened this issue Jul 2, 2022 · 7 comments · May be fixed by ragrawal1234/remix#2

Comments

@alexalexyang
Copy link

alexalexyang commented Jul 2, 2022

What version of Remix are you using?

1.6.3

Steps to Reproduce

  • Install styled components
  • Build something highly visible in styled components just so it's easier to see it break
  • Render hours, eg:
    const now = new Date();
    const hr = now.getHours();
    ...
    return (<p>{hr}</p>)
    
  • Deploy to something like Vercel or set local dev environment to UTC time before starting up your Remix app

Expected Behavior

Styled components doesn't break.

Actual Behavior

Styled components breaks with error: "Remix Hydration failed: UI on server and client do not match".

@noahstegmaier and I suspect that styled components breaks because hours is rendered in UTC time on the server but locale time on the client.

To be honest, we're not sure if this is a bug or if we're supposed to handle this ourselves. So, also not sure if this should be asked on Remix or Styled components GitHub issues.

@machour
Copy link
Collaborator

machour commented Jul 3, 2022

Suggestion : do all the date related operation server side, eg. your loader, and return the current date from it. This way you'll avoid any local vs server side date reconciliation issues

@alexalexyang
Copy link
Author

After enough headspace and hindsight, I believe this issue is not a bug and should be handled ourselves.

One way is as @machour describes it (thanks!). Another way, which fits my use case, is to render the date after everything has mounted.

@msevestre
Copy link

Another way, which fits my use case, is to render the date after everything has mounted.

How are you doing this?

Let say I want to show something like Good Morning, Good Afternoon based on the time of day. This should only be done using the client side time and not the server side time. I am a bit puzzled as to how this should be done only in the client

@kiliman
Copy link
Collaborator

kiliman commented Aug 5, 2022

You can use <ClientOnly> from remix-utils

function greeting() {
  const hour = new Date().getHours()
  const message = hour > 6 && hour < 12 ? 'Good Morning'
                  : hour >= 12 && hour < 18 ? 'Good Afternoon' 
                  : 'Good Evening'
  return message
}

export default function Greeting() {
  // greeting() called only on client
  return <ClientOnly>{() => <p>{greeting()}</p>}</ClientOnly>
}

@msevestre
Copy link

oh oh this is awesome. Did not know about this.
Will it create some kind of layout shift when rendering? I guess it's better than seeing Good Afternoon then Good Morning.

@alexalexyang
Copy link
Author

alexalexyang commented Aug 5, 2022

@msevestre, my use case requires that the time be saved in a database beforehand. So my solution uses useEffect:

const [now, setNow] = useState<Date>();
const loaderData = useLoaderData<string>();

useEffect(() => {
  if (!loaderData) {
    return;
  }

  setNow(JSON.parse(loaderData));
}, [loaderData]);

return <>{now.toLocaleTimeString([], {
            hour: "2-digit",
            minute: "2-digit",
          })}</>

Two things. I've not tried @kiliman's solution. Looks good, could work for you. And, there's been new talk about how useEffect should/should not be used but I've not looked into it.

@kiliman
Copy link
Collaborator

kiliman commented Aug 5, 2022

Since the server won't render anything, it may cause shift depending on what's around it... but you won't see text change. If you need to, you can always set a fallback that reserves some space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants