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

Support for next.js #204

Open
ajayjaggi97 opened this issue Jun 22, 2022 · 4 comments
Open

Support for next.js #204

ajayjaggi97 opened this issue Jun 22, 2022 · 4 comments

Comments

@ajayjaggi97
Copy link

Can you pls share the insights of using isomorphic-style-loader with next.js. How can we pass the required context value of insertCss??

@Ainias
Copy link

Ainias commented Jul 8, 2022

@ajayjaggi97 I've tried for the last 3 days to get it to work with next.js and I'm finally happy to use it.
First of all: I want to use it for a component-library and not directly in next.js. I think for direct usage, next.js already has a nice system through the *.module.scss/css-files.

This is where the magic happens: Here is the content of my _app.tsx:

export default function MyApp({ }: AppProps) {
    const styles: string[] = useMemo(() => [], []);

    const addStyles = useCallback(
        (...newStyles) => {
            if (typeof document === 'undefined') {
                styles.push(...newStyles.map((s) => s._getCss()));
            } else {
                newStyles.forEach((s) => s._insertCss());
            }
        },
        [styles]
    );

    return (
        <>
            <StyleProvider value={{ insertCss: addStyles }}>
                <ColorInput />
            </StyleProvider>
            <StyleRenderer styles={styles} />
        </>
    );
}

and my StyleRenderer.tsx:

export type StyleRendererProps = { styles: string[] };

export function StyleRenderer({ styles }: StyleRendererProps) {
    return (
        <Head>
            <style>{styles.join()}</style>
        </Head>
    );
}

Note that I use useMemo in order to save the styles and StyleRenderer, which only displays the styles. This is because of how nextjs works. Once the rendermethod is done, you can't trigger an rerender on the server, regardless what you do (or at least I could not trigger one). But subcomponents are still rendering. Since the components are called top-down, the ColorInput is called before the StyleRenderer. Inside the ColorInput I use the useStyles hook, which calls addStyles from _app.tsx. Since I used useMemo for styles, it is the same instance inside addStyles as is passed to StyleRenderer,
Since StyleRenderer renders last, it will render all the styles needed inside the server rendering.
On the client, I just use the s._insertCss() method without any problems.

And also note that I did not use StyleContext.Provider but StyleProvier which is an reexport of StyleContext.Provider from my component-library. This is needed or else the context used from useStyles inside the library is a different one than the one provides through StyleContext.Provider inside next.js

@ajayjaggi97
Copy link
Author

Hey @Ainias .Thanks for the solution. I had the similar use case where we had a components library.

@tagerwang
Copy link

Do you have a specific example for reference? thank you

@childrentime
Copy link

@Ainias @ajayjaggi97 can you give a example? I'm very curious about how to actually implement this🤪.

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

No branches or pull requests

4 participants