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

examples/next: fix unstyled flash #277

Merged
merged 15 commits into from
Aug 12, 2019
Merged

examples/next: fix unstyled flash #277

merged 15 commits into from
Aug 12, 2019

Conversation

jordanoverbye
Copy link
Contributor

Hello 👋

This PR attempts to fix #270

So I don't think it's possible to create a theme-ui-next plugin as we have to do things that plugins aren't able to do (like wrapping the App in a ThemeProvider). So instead I have done something else:

  1. Extract the noflash function in gatsby-plugin-theme-ui into its own function that theme-ui exports called applyColorModeFromLocalStorage.
  2. Update the next example to use light/dark mode and also use the applyColorModeFromLocalStorage which prevents the unstyled flash.

Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
<Html>
<Head />
<body>
<script
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this! I wonder if it might make more sense from an API standpoint to make this a component, since this and gatsby-ssr.js both use a script element

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a good idea! I was thinking that after I submitted this PR. The reason I didn't do that is because in gatsby-ssr.js it's using a js function and not JSX. But I will update

@jletey
Copy link
Contributor

jletey commented Aug 7, 2019

@jxnblk @jordanoverbye When I run your code ... I get a module not found error for @emotion/core

After installing it, everything works fine!

@jordanoverbye
Copy link
Contributor Author

@johnletey good pickup! I'll fix that.

Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
@jordanoverbye
Copy link
Contributor Author

jordanoverbye commented Aug 8, 2019

Hey @jxnblk , do you mind taking another look at this please? Also, I'm not 100% on the name ApplyColorModeFromLocalStorage...

Signed-off-by: Jordan Overbye <jordanoverbye@gmail.com>
@@ -68,4 +68,17 @@ const bodyColor = theme => ({

export const ColorMode = () => <Global styles={bodyColor} />

export const ApplyColorModeFromLocalStorage = () => (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as names go, what about

Suggested change
export const ApplyColorModeFromLocalStorage = () => (
export const InitializeColorMode = () => (

@jxnblk
Copy link
Member

jxnblk commented Aug 9, 2019

This is looking great! Not sure about what would make most sense for the component name, but other than that this seems great! We can add docs for Next.js usage after this is merged in

jordanoverbye and others added 3 commits August 10, 2019 15:04
@jordanoverbye
Copy link
Contributor Author

Thanks @jxnblk , I've just updated those changes

@jletey
Copy link
Contributor

jletey commented Aug 10, 2019

@jordanoverbye @jxnblk When I use the newest update _document.js, I get the following error:

at Object.renderToHTML (/Users/john/Desktop/learn-anything/node_modules/next-server/dist/server/render.js:277:16) name: 'Invariant Violation', framesToPop: 1 }
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check your code at _document.js:16.
    in MyDocument
    in Context.Provider

@jordanoverbye
Copy link
Contributor Author

jordanoverbye commented Aug 10, 2019

Hey @johnletey

So because this example lives outside the /packages folder, we have to manually link the latest version of theme-ui into examples/next.

I think the problem you are seeing is because haven't done this step and we have added a new API which doesn't exist in the current version of theme-ui.

cd ~/path/to/theme-ui/packages/theme-ui
yarn prepare
yarn link
cd ../../examples/next 
yarn link "theme-ui"
yarn dev

Let me know if that fixes it for you.

@jletey
Copy link
Contributor

jletey commented Aug 11, 2019

No @jordanoverbye ... I'm literally just copying-n-pasting your code into a different Next.js project that I'm working on and I need Theme UI for, and the newest changes to _document.js cause errors when running the site

@jordanoverbye
Copy link
Contributor Author

Hey @johnletey

Oh right that makes sense - but the error you are seeing is caused by the same thing though. In your NextJS project you have theme-ui installed via NPM. The latest version of theme-ui on NPM does not export the component InitializeColorMode which I have introduced in this PR. So it will fail when it tries to render something that doesn't exist.

What you can do for now is just copy the source code of InitializeColorMode and paste it into _document.js. Then, once this PR is merged in you can upgrade your theme-ui package and remove this hack.

import React from 'react'
import Document, { Html, Head, Main, NextScript } from 'next/document'
// import { InitializeColorMode } from 'theme-ui'

// Remove this once this PR is merged
const InitializeColorMode = () => (
  <script
    key="theme-ui-no-flash"
    dangerouslySetInnerHTML={{
      __html: `(function() { try {
        var mode = localStorage.getItem('theme-ui-color-mode');
        if (!mode) return
        document.body.classList.add('theme-ui-' + mode);
      } catch (e) {} })();`,
    }}
  />
)

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx)
    return initialProps
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <InitializeColorMode />
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

@jletey
Copy link
Contributor

jletey commented Aug 12, 2019

Wonderful ... thank you so much @jordanoverbye

Now I don't have an unstyled flash!

@jxnblk
Copy link
Member

jxnblk commented Aug 12, 2019

@jordanoverbye Thanks for working on this, this looks great!

@jxnblk jxnblk merged commit 60cda05 into system-ui:master Aug 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Next.js plugin
3 participants