16

I'm building a website with React and recently switched to using server-side rendering (SSR) for improved performance. One issue I ran into after this change is that when I format a time on the page (I'm using Moment.js) it renders incorrectly using the server's time zone.

How can I format the time using the client's time zone? Do I need to leave the time off on the server response and have the client render that afterwards?

Liron Yahdav
  • 10,152
  • 8
  • 68
  • 104

3 Answers3

4

Do I need to leave the time off on the server response and have the client render that afterwards?

Unfortunately yes.

You can build a utility component to make this less tedious.

Class component:

// utility
import React, { Component } from 'react';

// Class component
export default class ClientRender extends Component {
  state = { isMounted: false };
  
  componentDidMount () {
    this.setState({ isMounted: true });
  }

  render () {
    const { children } = this.props;
    const { isMounted } = this.state;
    
    return isMounted ? children : null;
  }
}

// Function component
export default function ClientRender({ children }) {
  const [isMounted, setIsMounted] = React.useState(false);

  React.useEffect(() => {
    setIsMounted(true);
  }, []);

  return isMounted ? children : null;
}

// in your app
import React from 'react';
import moment from 'moment';

import ClientRender from './path/to/client-render';

export default function MyComponent (props) {
  return (
    <div>
      <ClientRender>{moment(props.timeUTC * 1000).format('LLL')}</ClientRender>
    </div>
  );
}
Mo Kouli
  • 92
  • 1
  • 4
  • 1
    Why not render server-side with a default timezone in state and set the client timezone to state in `componentDidMount`? – coreyward Jun 16 '18 at 19:54
  • @coreyward would prefer to never show the user a potentially wrong time. – Liron Yahdav Jul 06 '18 at 23:20
  • @LironYahdav The only case where that would happen is if they have JavaScript disabled, in which case this solution won't work. – coreyward Jul 07 '18 at 00:54
  • 4
    Maybe I didn't explain myself well enough. I meant that I don't want to render server-side with a default timezone because that means that end users will see times formatted in a potentially incorrect timezone for a brief moment. There's no way for that default timezone to be correct for all users. This can happen when JS is enabled. – Liron Yahdav Jul 07 '18 at 01:00
2

I haven't done this with React, specifically, but the general approach is to render a <time> element (documentation here) with a full date/time format that contains the timezone, then adjust the text output client-side.

This should be fairly straightforward when you rehydrate client-side; react-moment also accepts a timezone if you're rendering server-side per request… 

coreyward
  • 77,547
  • 20
  • 137
  • 166
0

I have the same issue.

One thing that you may try is to set a cookie client-side with the timezone as value.

The first visit of a client will always be an issue so be prepared to use a default timezone or delay rendering (with didMount event).

But once a client comes back with said cookie you can use that cookie value as the timezone for date and time string rendering.

Not tried it yet, I will try to think about updating that post if I'm successful

Apolo
  • 3,844
  • 1
  • 21
  • 51