次へのテーマの追加.スタイルのコンポーネント、mobx、およびタイプスクリプトと


ダークモード対ライトモード?


あなたのユーザーを決定しましょう.オプションをstyled-componentsmobxとの間でシームレスに切り替えるオプションを提供します.

始める

  • 依存関係をインストールする
  • テーマ定数を作成する
  • スタイルのコンポーネントを設定します.JS
  • スタイルコンポーネントのサーバー側機能を追加
    の永続的なデータモービルストアを作成する
  • は、グローバルスタイル
  • を作成します
    StyleProvider を作成する

  • テーマ
  • にタイプを加える

  • がそれを確実にすること

    インストール

  • 依存関係:yarn add styled-components mobx mobx-react
  • dev依存性: yarn add -D @types/styled-components
  • 2 .テーマ定数のファイルを作成する

    themes.constants.tsこのファイルでは、テーマやその他のリレーショナル定数を定義します.

  • const COLOURS = {
      black: '#000000',
      white: '#FFFFFF'
    }
    
  • ダークテーマ
  • const DARK_THEME = {
      name: 'dark',
      background: COLOURS.black,
      textPrimary: COLOURS.white
    }
    
  • ライトテーマ
  • const LIGHT_THEME = {
      name: 'light',
      background: COLOURS.white,
      textPrimary: COLOURS.black
    }
    
  • デフォルトのテーマをエクスポート
  • export const DEFAULT_THEME = 'dark'
    
  • テーマをエクスポートします
  • export const THEMES = {
      dark: DARK_THEME,
      light: LIGHT_THEME,
    }
    

    3 .次のスタイルコンポーネントを追加します。設定。jsファイル


    NextConfigオブジェクトで、キーペア値を追加します.
      compiler: {
        styledComponents: true,
      },
    

    4 . ServerStylesheetをCountドキュメントに追加します。TSX

    getInitialPropsメソッドを下に示すMyDocumentクラスに追加します.
    あなたが_document.tsxをすでに作成していないならば、あなたのpagesフォルダにそれを加えてください.ペーストします.
    import Document, {
      Html,
      Head,
      Main,
      NextScript,
      DocumentContext,
    } from 'next/document';
    import { ServerStyleSheet } from 'styled-components';
    
    class MyDocument extends Document {
      static async getInitialProps(ctx: DocumentContext) {
        const sheet = new ServerStyleSheet();
        const originalRenderPage = ctx.renderPage;
    
        try {
          ctx.renderPage = () =>
            originalRenderPage({
              enhanceApp: (App) => (props) =>
                sheet.collectStyles(<App {...props} />),
            });
    
          const initialProps = await Document.getInitialProps(ctx);
          return {
            ...initialProps,
            styles: [
              <>
                {initialProps.styles}
                {sheet.getStyleElement()}
              </>,
            ],
          };
        } finally {
          sheet.seal();
        }
      }
      render() {
        return (
          <Html>
            <Head>
            </Head>
            <body>
              <Main />
              <NextScript />
            </body>
          </Html>
        );
      }
    }
    
    export default MyDocument;
    
    

    localstorageで永続的なデータを許可するユーティリティ関数を作成する

    utils.ts
    export const setStorage = (key: string, value: unknown) => {
      window.localStorage.setItem(key, JSON.stringify(value));
    };
    export const getStorage = (key: string) => {
      const value = window.localStorage.getItem(key);
    
      if (value) {
        return JSON.parse(value);
      }
    };
    
    

    MOVXでUIストアを作成する

    uiStore.ts
    import { action, makeAutoObservable, observable } from 'mobx';
    import { setStorage } from './utils';
    
    type Themes = 'dark' | 'light';
    
    class UiStore {
      @observable
      private _theme: Themes = 'light';
    
      @observable
      private _initializing: boolean = true;
    
      constructor() {
        makeAutoObservable(this);
      }
    
      get theme() {
        return this._theme;
      }
      get initializing() {
        return this._initializing;
      }
    
      @action
      toggleTheme() {
        this._theme = this._theme === 'light' ? 'dark' : 'light';
        setStorage('theme', this._theme);
      }
    
      @action
      changeTheme(nameOfTheme: Themes) {
        this._theme = nameOfTheme;
      }
    
      @action
      finishInitializing() {
        this._initializing = false;
      }
    }
    
    export const uiStore = new UiStore();
    
    

    スタイルコンポーネントを使用したグローバルスタイルの作成


    スタイリングコンポーネントのテーマには次のようにアクセスできます.global-styles.ts
    export const GlobalStyle = createGlobalStyle`
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    
    html {
      background: ${({ theme }) => theme.colors.body};
    }
    
    `;
    

    StyleProviderの作成

    style-provider.tsx
    import { observer } from 'mobx-react';
    import { useEffect, ReactNode } from 'react';
    import { ThemeProvider } from 'styled-components';
    import { uiStore } from './uiStore';
    import { DEFAULT_THEME,  THEMES } from './theme.constants';
    import { GlobalStyle } from './global-styles`
    import { getStorage, setStorage } from './utils';
    
    interface OnlyChildren {
      children: ReactNode
    }
    
    const StyleProviderComponent = (props: OnlyChildren) => {
      const { children } = props;
      const { theme } = uiStore;
    
      useEffect(() => {
        if (!getStorage('theme')) {
          setStorage('theme', DEFAULT_THEME);
        }
        const storageThemeName = getStorage('theme');
        uiStore.changeTheme(storageThemeName);
        uiStore.finishInitializing();
      }, []);
    
      return (
        <ThemeProvider theme={THEMES[theme]}>
          <GlobalStyle />
          {children}
        </ThemeProvider>
      );
    };
    
    export const StyleProvider = observer(StyleProviderComponent);
    

    9 .テーマを入力する

    default-theme.d.ts
    import 'styled-components';
    
    declare module 'styled-components' {
      export interface DefaultTheme {
        name: string;
        colors: {
          primary: string;
          textPrimary: string;
        };
      }
    }
    

    10 .ページを提供します。TSX


    import type { AppProps } from 'next/app';
    import { StyleProvider } from './style-provider';
    
    function MyApp({ Component, pageProps }: AppProps) {
      return (
        <StyleProvider>
          <Component {...pageProps} />
        </StyleProvider>
      );
    }
    
    export default MyApp;
    

    ページ/インデックスで動作することをテストします。TSX


    import type { NextPage } from 'next';
    import Head from 'next/head';
    import { uiStore } from './uiStore';
    
    const Home: NextPage = () => {
      const { initializing } = uiStore;
    
      if (!initializing) {
        return <h1>Loading...</h1>;
      }
    
      return (
        <>
          <Head>
            <title>
              Adding themes to Next.js with styled-components, mobx, and typescript
            </title>
            <meta name='description' content='Tutorial by Zach Nugent' />
            <link rel='icon' href='/favicon.ico' />
          </Head>
          <button onClick={() => uiStore.toggleTheme()}>Switch theme</button>
        </>
      )
    }
    export default Home
    
    
    スタイルのコンポーネントのテーマにアクセスすることができますバックコールの間にコールバック機能(EX : ${({ theme }) => theme.colors.textPrimary})を追加します.
    例:
    const Button = styled.button`
      background: ${({ theme }) => theme.colors.body};
      border: 1px solid ${({ theme }) => theme.colors.accent};
      color: ${({ theme }) => theme.colors.textPrimary};
    `
    
    読書ありがとう🙂