Giter VIP home page Giter VIP logo

react-typescript-sfc's Introduction

Typescript & React で Single File Components

経年劣化に耐える React のソフトウェア設計を考えるためのサンプルプロジェクト。
学習目的で、実際に React を使ってアプリケーション開発を行う上で必要だと思ったものをまとめてみました。

目次

デモ

URL(デプロイ先)

Storybook - スタイルガイド(GitHub Pages)
https://imamachi-n.github.io/react-typescript-sfc/

React アプリケーション(AWS: CloudFront/S3)
準備中。。。

画面スクリーンショット

トップページ - スクロール

  • ランディングページによくある、リンクをクリックすると自動スクロールされる仕組み。
  • トップページの先頭に戻るボタンを表示(スクロールをトリガーにする)。

React_SFC_1

レスポンシブ UI(Mobile 用と Desktop 用)

  • Desktop 用の画面では、ナビゲーションをページ上部に表示させる。
  • Mobile 用の画面では、ナビゲーションをページ下部に表示させる(指で押しやすいため)。

React_SFC_2

設計・アーキテクチャ

Single File Components for React

準備中。

参考資料
経年劣化に耐える ReactComponent の書き方

CloudFront/S3 with AWS CDK

準備中。

詳細

TypeScript & React のプロジェクトを作成

npx create-react-app react-typescript-sfc --template typescript

Adding TypeScript
https://create-react-app.dev/docs/adding-typescript/

絶対パスで React コンポーネントをインポートできるようにする

相対パスだと、リファクタリングによってコンポーネントの配置を変更した場合に、インポート先もすべて変更する必要が出てくる。絶対パスを指定することにより、上記の問題を回避する。

設定方法としては、tsconfig.json に以下の設定を追加するだけ。

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

例えば、components/Button を以下のように絶対パスを使ってインポートできるようになる。

import Button from 'components/Button';

おそらく、絶対パスにすると補完が効かなくなるので、さらに、path-intellisense を拡張機能として追加する。

参考資料
Create React App - Absolute Imports
VS Code: “Cannot find module” from root path

ESLint & Prettier の導入

まず、コーディングスタイルを統一するために、ESLint と Prettier の導入を行う。

yarn add -D \
eslint @types/eslint \
prettier @types/prettier \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
eslint-config-airbnb \
eslint-config-prettier \
eslint-plugin-import \
eslint-plugin-react \
eslint-plugin-react-hooks
eslint-plugin-jsx-a11y \
eslint-plugin-jest \
eslint-plugin-prefer-arrow \
eslint-plugin-mdx \
eslint-plugin-prettier \
@types/eslint-plugin-prettier

以下の各種設定を 設定ファイル .eslitrc.js に記述する。デフォルトの .eslitrc の JSON ファイルの場合、キーにいちいちダブルクオーテーションをつけないといけないので、JSファイル にしたほうが書きやすいと思う。

eslint-config-airbnb

AirBnb が提供する ESLint の有名な共通設定を導入する。 eslint-config-airbnb を導入する際、以下のパッケージが必要になる。

  • eslint
  • eslint-plugin-import
  • eslint-plugin-react
  • eslint-plugin-react-hooks
  • eslint-plugin-jsx-a11y
  • @typescript-eslint/parser

eslint-config-airbnb の導入
https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb#eslint-config-airbnb-1

eslint-plugin-react

eslint-plugin-react は React 固有の lint の設定を追加するためのプラグイン。使用するために、extendsplugins に設定を追加する。

extends: [
  'eslint:recommended',
  'plugin:react/recommended',
],

plugins: [
  'react'
],

また、React のバージョンを自動的に特定するために、detect の設定を行う(将来的に、detect がデフォルトになる予定なので、いずれ設定する必要がなくなる)。

settings: {
  react: {
    version: 'detect',
  },
}

さらに、JSX のサポート(ESLint 2+)を追加するために、

parserOptions: {
  ecmaFeatures: {
    jsx: true,
  },
},

eslint-plugin-react の設定
https://github.com/yannickcr/eslint-plugin-react#configuration

eslint-plugin-react-hooks

eslint-plugin-react-hooksは、React Hook に対する lint を設定するためのプラグイン。マニュアル設定を適応する場合、以下のように設定する。

plugins: [
  "react-hooks"
],

rules: {
  'react-hooks/rules-of-hooks': 'error',
  'react-hooks/exhaustive-deps': 'error',
},

eslint-plugin-import

eslint-plugin-import は ES2015+ (ES6+) import/export syntax の lint に使われる。 デフォルトではすべてのルールが無効化されているので、extends 内でプラグインの設定を行うか、

extends: [
  'eslint:recommended',
  'plugin:import/errors',
  'plugin:import/warnings',
],

個別にルールを rules 内に書き込む必要がある(両方、設定することも可能)。

plugins: [
    'import',
],

rules: {
    'import/extensions': [
      'error',
      'always',
      {
        js: 'never',
        jsx: 'never',
        ts: 'never',
        tsx: 'never',
      },
    ],
    'import/prefer-default-export': 'off',
}

また、TypeScript を使っている場合は、次の設定を追加する必要がある。このとき、@typescript-eslint/parser パッケージが依存パッケージに含める必要がある。

extends: [
  'eslint:recommended',
  'plugin:import/errors',
  'plugin:import/warnings',
  'plugin:import/typescript', // 追加
],

eslint-plugin-import のインストール方法
https://github.com/benmosher/eslint-plugin-import#installation

ルールを適応するファイルを以下のように指定する。import/resolver では、src ディレクトリ以下の tstsx などの拡張子を持つファイルのみを対象とする。

settings: {
  'import/resolver': {
    node: {
      extensions: ['.js', 'jsx', '.ts', '.tsx'],
      paths: ['src'],
    },
  },
}

また、import/parsers を使うことで、対象のファイルに対して、指定した parser を使用することができる。以下では、tstsx の拡張子を持つファイルに対して、TypeScript 用の parser を使うように設定している。

settings: {
  'import/parsers': {
    '@typescript-eslint/parser': ['.ts', '.tsx'],
  },
}

eslint-plugin-import の設定
https://github.com/benmosher/eslint-plugin-import#settings

eslint-plugin-jsx-a11y

eslint-plugin-jsx-a11y は Web アクセシビリティに関する lint を行うためのプラグイン。plugins で以下のように設定する。

"plugins": [
  "jsx-a11y",
]

推奨設定を適応する場合、以下のように設定する。

extends: [
  'plugin:jsx-a11y/recommended',
]

eslint-plugin-jsx-a11y の使い方
https://github.com/evcohen/eslint-plugin-jsx-a11y#usage

eslint-plugin-jest

eslint-plugin-jest は Jest に対する lint を行うためのプラグイン。以下では、推奨設定とスタイルを強制する設定を示した。

extends: [
  'plugin:jest/recommended',
  'plugin:jest/style',
],

plugins: [
  'jest',
],

また、Jest が提供するグローバル変数をホワイトリストに追加するために、以下のように設定を行う。

env: {
  'jest/globals': true,
},

eslint-plugin-jest の使い方
https://github.com/jest-community/eslint-plugin-jest#usage

eslint-plugin-prefer-arrow

eslint-plugin-prefer-arrow はアロー関数に関する lint を行うためのプラグイン。以下のように設定を行う。

plugins: [
  'prefer-arrow',
],

rules: {
  'prefer-arrow/prefer-arrow-functions': [
    'error',
    {
      disallowPrototype: true,
      singleReturnOnly: true,
      classPropertiesAllowed: false,
    },
  ],
}

eslint-plugin-prefer-arrow の使い方
https://github.com/TristonJ/eslint-plugin-prefer-arrow#installations

eslint-plugin-mdx

eslint-plugin-mdx は MDX ファイル(JSX/TSX 内に markdown ファイルがかけるようにした拡張構文)を lint するためのプラグイン。以下のように設定を行う。

{
  extends: ["plugin:mdx/recommended"]
}

eslint-plugin-mdx の使い方
https://github.com/mdx-js/eslint-mdx#install

@typescript-eslint

@typescript-eslint/parser

TypeScript で型の情報を必要とする場合は、必須の設定。

parserOptions: {
  project: './tsconfig.json',
}

@typescript-eslint/parser の使い方
https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#parseroptionsproject

@typescript-eslint/eslint-plugin

@typescript-eslint/eslint-plugin は TypeScript の lint を行うためのプラグイン。@typescript-eslint/parser がインストールされていることが前提。推奨設定は以下のように設定を行う。

extends: [
  'plugin:import/typescript',
  'plugin:@typescript-eslint/eslint-recommended',
  'plugin:@typescript-eslint/recommended',
],

parser: '@typescript-eslint/parser',
plugins: [
  '@typescript-eslint',
],
rules: {
  '@typescript-eslint/explicit-function-return-type': 'off',
  '@typescript-eslint/explicit-member-accessibility': 'off',
  indent: 'off',
  '@typescript-eslint/indent': 'off',
  '@typescript-eslint/no-unnecessary-type-assertion': 'error',
}

@typescript-eslint/eslint-plugin の使い方
https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage

eslint-plugin-prettier

eslint-plugin-prettier は Prettier と ESLint を連携させるためのプラグイン。推奨設定は以下のように設定を行う。また、他のプラグインと連携を行うことできる。

extends: [
  'plugin:prettier/recommended',
  'prettier/react',
  'prettier/standard',
],

マニュアルで設定を変更する場合は、以下のように設定を行う。

extends: [
  'prettier',
],

plugins: [
  'prettier',
],

rules: {
  'prettier/prettier': 'error',
}

eslint-plugin-prettier の使い方
https://github.com/prettier/eslint-plugin-prettier#recommended-configuration
連携できる ESLint プラグインの一覧
https://github.com/prettier/eslint-config-prettier/blob/master/README.md#installation

Stylelint の導入(オプション)

Styled-components に Stylelint と Prettier を導入する。ただし、Styled-components の場合、--fix オプションを使うことができないため、自動で修正することは不可能(問題箇所の検知のみ可能)。

yarn add -D \
stylelint \
@types/stylelint \
stylelint-processor-styled-components \
stylelint-config-styled-components \
stylelint-config-recommended \
stylelint-config-prettier

Styled-components

.stylelintrc ファイルを作成して、以下の Styled-components の設定を追加する。

{
  "processors": ["stylelint-processor-styled-components"],
  "extends": [
    "stylelint-config-recommended",
    "stylelint-config-styled-components"
  ]
}

Styled-components tooling
https://styled-components.com/docs/tooling#stylelint

stylelint-config-prettier

Prettier と競合するルールを排除する。

{
  "extends": ["stylelint-config-prettier"]
}

stylelint-config-prettier の使い方
https://github.com/prettier/stylelint-config-prettier#installation

husky & lint-staged の導入

yarn add husky lint-staged

lint-staged

lint-staged を使うことで、staged git ファイルのみに対して lint をコマンドで実行することができる。

{
  "lint-staged": {
    "src/**/*.{js,jsx,ts,tsx}": ["eslint --fix", "git add"]
  }
}

lint-staged の使い方
https://github.com/okonet/lint-staged#configuration

hasky

husky は git での commit・push の前に実行するコマンドを設定できる。ここでは、lint-staged と合わせて使用し、コミット時に lint が実行されるように設定する。package.json を以下のように設定する。

// package.json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  }
}

Husky の使い方
https://github.com/typicode/husky#install

Redux の導入

yarn add redux react-redux @types/redux @types/react-redux

React Redux - Quick Start
https://react-redux.js.org/introduction/quick-start

Redux - Configuring Your Store
https://redux-docs.netlify.com/recipes/configuring-your-store/

複数の reducer を結合する

Using combineReducers
https://redux-docs.netlify.com/recipes/structuring-reducers/using-combinereducers

React Router の導入

yarn add react-router-dom @types/react-router-dom

React Router - Quick Start
https://reacttraining.com/react-router/web/guides/quick-start

画面遷移時のスクロール位置の初期化

デフォルトの設定では、画面遷移時に前のページのスクロール位置が残ってしまい、ページの最上部から表示されない問題が発生する。

以下の設定を追加し、問題を解消する必要がある。

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

export default function ScrollRestoration() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import ScrollRestoration from 'components/Common/ScrollRestoration';

function App() {
  return (
    <Router>
      <ScrollToTop />
      <App />
    </Router>
  );
}

React Router - Scroll Restoration
https://reacttraining.com/react-router/web/guides/scroll-restoration

React Router と Redux の統合

React Router - Redux Integration
https://reacttraining.com/react-router/web/guides/redux-integration

Styled-components の導入

Global CSS を指定する方法

createGlobalStyle
https://styled-components.com/docs/api#createglobalstyle

Material-UI の導入

yarn add @material-ui/core @material-ui/icons

Material-UI のインストール
https://material-ui.com/getting-started/installation/

Styled-components で定義したスタイルを優先する

CSS インジェクションの順番を、Styled-components が最も優先されるように指定する。

ルートコンポーネントをラップする形で、StylesProvider コンポーネントを使用し、プロパティに injectFirst を指定することで、Styled-components を最も優先するように設定できる。

import { StylesProvider } from '@material-ui/core/styles';

ReactDOM.render(
  <StylesProvider injectFirst>
    <App />
  </StylesProvider>,
  document.getElementById('root'),
);

Controlling priority
https://material-ui.com/guides/interoperability/#controlling-priority-%EF%B8%8F-3

injectFirst
https://material-ui.com/styles/advanced/#injectfirst

テーマカラーを設定する

Material-UI の ThemeProvider を用いて、カスタムテーマを対象のコンポーネントに適応する。このとき、Styled-components でも、Material-UI のカスタムテーマを使うために、ThemeProvider を併用する。

モジュール名が同じため、以下のように、Material-UI の ThemeProviderMaterialThemeProvider、Styled-components の ThemeProviderStyledThemeProvider と定義する。

import { ThemeProvider as MaterialThemeProvider } from '@material-ui/styles';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';

ReactDOM.render(
  <MaterialThemeProvider theme={theme}>
    <StyledThemeProvider theme={theme}>
      <App />
    </StyledThemeProvider>
  </MaterialThemeProvider>,
  document.getElementById('root'),
);

カスタムテーマを使用する場合は、以下のように props からアクセスできる。ただし、上記の設定のみだと、TypeScript の場合、theme の型が any になってしまう。

import { AppBar } from '@material-ui/core';
import styled from 'styled-components';

const StyledAppBar = styled(AppBar)`
  background-color: ${props => props.theme.palette.primary.main};
`;

そこで、Styled-components の TypeScript の型を拡張する。具体的には、Material-UI の Theme を継承した、DefaultTheme を新たに定義する。ファイル名は、styled.d.ts とする。

DefaultThemeprops.theme のインターフェースとして使用される。デフォルトでは、DefaultTheme は未定義なので、Material-UI の Theme を継承して、カスタムテーマの型を定義している。

// import original module declarations
import 'styled-components';
import { Theme } from '@material-ui/core';

// and extend them!
declare module 'styled-components' {
  export interface DefaultTheme extends Theme {} // eslint-disable-line
}

ESLint のせいで、interface の中身が空の場合、エラーとなるため、// eslint-disable-line を指定して、ESLint を無視する(あくまで例外的な処置)。 これにより、VSCode 上で補完が効くようになる。

参考資料
Material-UI のテーマのカスタマイズ
Material-UI のカスタムテーマをコンポーネントに適応する方法
How to use Material-UI theme with styled-components?
Styled-components で TypeScript の型定義ファイルを設定する
Material-UI と styled components のテーマの共通化

上部に固定されたヘッダーを作成

React.cloneElement を使って、子コンポーネントに elevationprops として渡す。

カスタム Hook である useScrollTrigger を使うことで、スクロールをトリガーとして、対象のコンポーネント(ヘッダーなど)を上部に配置する(デフォルトで elevation の値が 4 であり、スクロール時にこれを 0 にすることで、対象のコンポーネントが上部に固定される)。

import React from 'react';
import { useScrollTrigger } from '@material-ui/core';

interface ScrollProps {
  children: React.ReactElement;
}

export default function ElevationScroll(props: ScrollProps) {
  const { children } = props;

  const trigger = useScrollTrigger({
    disableHysteresis: true,
    threshold: 0,
  });

  return React.cloneElement(children, {
    elevation: trigger ? 4 : 0,
  });
}

参考資料
Material-UI - Elevate App Bar
React - cloneElement()

Grid React component のスクリーンサイズに応じた調節

innerWidth  |xs      sm       md       lg       xl
            |--------|--------|--------|--------|-------->
width       |   xs   |   sm   |   md   |   lg   |   xl

smUp        |   show | hide
mdDown      |                     hide | show

参考資料
Grid - How it works
Grid API

画面サイズに合わせて、React コンポーネントを表示・非表示をコントロール

Mobile 用と Desktop 用で画面の表示を切り替えるのに有用。

// 1. Import Layer
import React from 'react';
import styled from 'styled-components';
import { Hidden } from '@material-ui/core';
import { ContaineredTitle, Title } from './Title';
import { ContaineredScrollButton } from './ScrollButton';
import { ContaineredToDoButton } from './TodoButton';
import { ContaineredApiButton } from './ApiButton';

// 2. Types Layer
type Props = {
  className?: string;
};

// 3. DOM Layer
const LeftSide: React.FC<Props> = props => {
  const { className } = props;

  return (
    <div className={className}>
      {/* For mobile */}
      <Hidden mdUp>
        <Title />
      </Hidden>

      {/* For Desktop */}
      <Hidden smDown>
        <ContaineredTitle />
        <ContaineredScrollButton />
        <ContaineredToDoButton />
        <ContaineredApiButton />
      </Hidden>
    </div>
  );
};

// 4. Style Layer
export const StyledLeftSide = styled(LeftSide)`
  display: flex;
`;

export default StyledLeftSide;

Material-UI - Hidden
https://material-ui.com/components/hidden/#breakpoint-up

画面トップへスクロールして戻るボタン

ScrollTop コンポーネント

// 1. Import Layer
import React from 'react';
import styled from 'styled-components';
import { useScrollTrigger, Zoom } from '@material-ui/core';

type ContainerProps = {
  children: React.ReactElement;
};

type Props = {
  className?: string;
  trigger: boolean;
  handleClick: (event: React.MouseEvent<HTMLDivElement>) => void;
} & ContainerProps;

// 3. DOM Layer
const ScrollTop: React.FC<Props> = props => {
  const { className, children, trigger, handleClick } = props;

  return (
    <>
      <Zoom in={trigger}>
        <div className={className} onClick={handleClick} role="presentation">
          {children}
        </div>
      </Zoom>
    </>
  );
};

// 4. Style Layer
export const StyledScrollTop = styled(ScrollTop)`
  position: fixed;
  bottom: ${props => props.theme.spacing(2)}px;
  right: ${props => props.theme.spacing(2)}px;
`;

// 5. Container Layer
export const ContaineredScrollTop: React.FC<ContainerProps> = props => {
  const trigger = useScrollTrigger({
    disableHysteresis: true,
    threshold: 100,
  });

  const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
    // TODO: アンカーに`id="#back-to-top-anchor"`を設定する必要あり。
    const anchor = (
      (event.target as HTMLDivElement).ownerDocument || document
    ).querySelector('#back-to-top-anchor');

    if (anchor) {
      anchor.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  };

  return (
    <StyledScrollTop {...props} trigger={trigger} handleClick={handleClick} />
  );
};

export default ContaineredScrollTop;

ScrollTopButton コンポーネント

// 1. Import Layer
import React from 'react';
import styled from 'styled-components';
import { ContaineredScrollTop } from 'components/Common/ScrollTop';
import { Fab } from '@material-ui/core';
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';

// 2. Types Layer
type Props = {
  className?: string;
};

// 3. DOM Layer
const ScrollTopButton: React.FC<Props> = props => {
  const { className } = props;

  return (
    <div className={className}>
      <ContaineredScrollTop {...props}>
        <Fab color="primary" size="small" aria-label="scroll back to top">
          <KeyboardArrowUpIcon />
        </Fab>
      </ContaineredScrollTop>
    </div>
  );
};

// 4. Style Layer
export const StyledScrollTopButton = styled(ScrollTopButton)``;

export default StyledScrollTopButton;

使用例

// 1. Import Layer
import React from 'react';
import styled from 'styled-components';
import { StyledScrollTopButton } from 'components/Common/ScrollTop/ScrollTopButton';
import { Menu } from './components/Menu';
import { Contents } from './components/Contents';

// 2. Types Layer
type Props = {
  className?: string;
};

// 3. DOM Layer
const App: React.FC<Props> = props => {
  const { className } = props;

  return (
    <Router>
      <div className={className}>
        <Menu />

        {/* Anchor for ScrollToTop */}
        <div id="back-to-top-anchor" />

        <Contents />

        {/* ScrollToTop Button */}
        <StyledScrollTopButton />
      </div>
    </Router>
  );
};

// 4. Style Layer
const StyledApp = styled(App)`
  background-color: #282c34;
  font-size: calc(10px + 2vmin);
  color: white;
`;

export default StyledApp;

Material-UI - Back to top
MDN - Element.scrollIntoView()

React Helmet の導入

yarn add react-helmet @types/react-helmet

ヘッダー情報を追加する

メタ情報やタイトルなどをヘッダー情報として追加することができる。

// 1. Import Layer
import React from 'react';
import { Helmet } from 'react-helmet';

// 2. Types Layer
type Props = {};

// 3. DOM Layer
export const Header: React.FC<Props> = () => {
  return (
    <>
      <Helmet>
        <meta charSet="utf-8" />
        <title>React & TypeScript SFC - TopPage</title>
        <link
          rel="GitHub"
          href="https://github.com/Imamachi-n/react-typescript-sfc"
        />
      </Helmet>
    </>
  );
};

React Helmet の使い方
https://github.com/nfl/react-helmet#example

Storybook の導入(Create React App 用)

以下のコマンドを実行すると、Storybook を動かすのに必要なパッケージやファイル・コマンド群をすべて自動で用意してくれる(TypeScript への対応もやってくれるため、他に設定はいらない)。

npx -p @storybook/cli sb init --type react_scripts

.storybook/main.js ファイルを以下の通り書き換える。.js.(js|jsx|ts|tsx) に変更するだけ。

module.exports = {
  stories: ['../src/**/*.stories.(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
  ],
};

参考文献
Storybook - Storybook for React
Storybook - TypeScript Config

Storybook の作成

ここでは、Component Story Format (CSF) での記述方法を説明する。

以下に例を示す。

import React from 'react';
import { action } from '@storybook/addon-actions';
import { StyledBottomNavi } from 'components/BottomNavigation';

export default {
  title: 'BottomNavi',
  component: StyledBottomNavi,
};

export const BottomNavi = () => (
  <StyledBottomNavi
    handleClick4Home={action('Home')}
    handleClick4Scroll={action('Scroll')}
    handleClick4Todo={action('Todo')}
    handleClick4Api={action('Api')}
  />
);

export default

プロパティ 説明
tille サイドメニューに表示されるタイトル(詳細は下記参照)。
component 対象のコンポーネントを指定。

タイトルは、以下のように変換される。

name -> 'Name'
someName -> 'Some Name'
someNAME -> 'Some NAME'
some_custom_NAME -> 'Some Custom NAME'
someName1234 -> 'Some Name 1234'
someName1_2_3_4 -> 'Some Name 1 2 3 4'

export

あとは、表示させたいコンポーネントを export するだけ。表示されるコンポーネント名は、export したときの変数名で決まる(タイトル名の変換は上記と同様)。

参考資料
Storybook - Component Story Format (CSF)

MDX で Storybook ドキュメントを作成する

以下のコマンドを実行して、Storybook Docs のアドオンをインストールする。

yarn add -D @storybook/addon-docs

Storybook の設定ファイル .storybook/main.js に以下の設定を追加する。

module.exports = {
  stories: ['../src/**/*.stories.(js|jsx|ts|tsx|mdx)'],
  addons: ['@storybook/addon-docs'],
};

以下に例を示す。

import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
import { action } from '@storybook/addon-actions';
import { StyledBottomNavi } from 'components/BottomNavigation';

<Meta title="MDX/BottomNavi" component={StyledBottomNavi} />

# Bottom Navi

With `MDX` we can define a story for `BottomNavi` right in the middle of our
markdown documentation.

<Preview>
  <Story name="Botom Navi">
    <StyledBottomNavi
      handleClick4Home={action('Home')}
      handleClick4Scroll={action('Scroll')}
      handleClick4Todo={action('Todo')}
      handleClick4Api={action('Api')}
    />
  </Story>
</Preview>

<Meta> タグ

属性 説明
title サイドメニューに表示されるコンポーネント名を記載。/ で区切ることで階層も表現できる。
component 対象のコンポーネントを指定

<Preview> タグ

属性 説明
withSource ソースコードをデフォルトで表示させるかどうか(open/closed)。

<story> タグ

属性 説明
name サイドメニューに表示されるコンポーネント名。

このタグ内に、表示させたいコンポーネントを追加する。

参考資料
Storybook Docs - インストール方法
Storybook Docs MDX
Storybook の新しいアドオン addon-docs がいい感じ

Storybook Deployer を使って GitHub Pages へ Storybook をデプロイする

以下のコマンドを実行して、Storybook Deployer をインストールする。

yarn add -D @storybook/storybook-deployer

package.json ファイルに以下のコマンドを追加する。

{
  "scripts": {
    "deploy-storybook": "storybook-to-ghpages"
  }
}

以下のコマンドを実行して、GitHub Pages へ Storybook をデプロイする。

yarn deploy-storybook

GitHub Settings の GitHub Pages の項目で、gh-pages ブランチを使って、静的 HTML ファイルをデプロイする設定になっていることを確認。

参考資料
Storybook Deployer - インストール方法

Docker 上で開発環境をセットアップする

docker/node/Dockerfile を用意する。

FROM node:12.16.1-alpine3.11
WORKDIR /usr/src/app

docker-compose.yml ファイルを用意する。

version: '3'
services:
  web:
    build:
      context: ./docker/node
      dockerfile: Dockerfile
    volumes:
      - ./:/usr/src/app
    command: sh -c "yarn start"
    ports:
      - '3000:3000'

package.json ファイルに以下を追加する。

{
  "scripts": {
    "docker:build": "docker-compose build",
    "docker:install": "docker-compose run --rm web sh -c 'yarn install'",
    "docker:run": "docker-compose up",
    "docker:stop": "docker-compose down"
  }
}

yarn docker:build で Docker コンテナをビルドする。
yarn docker:install で Docker コンテナ内でyarn install を実行する(少なくとも、Docker for MacOS では遅くて使い物にならない…。10 数分かかる…)。
yarn docker:run で Docker コンテナを起動する。
yarn docker:stop で Docker コンテナを停止する。

Docker 環境内で create-react-app
https://qiita.com/mii288/items/aac597bc02575831ea90

VSCode の設定について

拡張機能の管理

  1. VSCode 上で、command + shift でコマンドパレットを開く。
  2. Extensions: Configure Recommended Extensions (Workspace Folder) を実行する。
  3. .vscode/extensions.json ファイルが作成される。
  4. 以下の図のように、拡張機能の略称をリストアップする。

extensions

"recommendations": [
  "equinusocio.vsc-material-theme",
],

VSCode - Workspace recommended extensions
https://code.visualstudio.com/docs/editor/extension-gallery#_workspace-recommended-extensions

VSCode の設定の管理

.vscode/settings.json 内に設定を書き込むことで、書き込んだ設定を対象のプロジェクトで使うことができる。

ファイルの保存を行ったときに、ESLint の修正が実行されるように設定する。

{
  "editor.codeActionsOnSave": { "source.fixAll.eslint": true },
  "editor.formatOnSave": true
}

既存の React プロジェクトのアップデート

Create React App

Create React App をアップデートする場合、Change Log に書かれているマイグレーション用のコマンドを実行すること。

Updating to New Releases
https://create-react-app.dev/docs/updating-to-new-releases/

Storybook

Storybook をアップデートする場合、Migration に記載されている内容をもとにマイグレーションを行う。

Storybook v5 以降、TypeScript へのデフォルト対応などを始めとするプリセット周りの整備が進み、更新頻度が高め。

React などの他のパッケージのアップグレード

以下のコマンドを実行することで、すべての依存パッケージのアップグレードを行うことができる。

yarn upgrade

Upgrade for Minor or Patch Releases
https://www.gatsbyjs.org/docs/upgrade-gatsby-and-dependencies/

参考資料

公式ドキュメント

react-typescript-sfc's People

Contributors

imamachi-n avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.