LoginSignup
19
16

More than 3 years have passed since last update.

TypeScriptを導入する前提でReact/Next.jsをはじめる

Last updated at Posted at 2020-12-03

この記事は「株式会社オープンストリーム "小ネタ" Advent Calendar 2020」の2日目の記事です。

はじめに

フロントエンドフレームワークのVueと比較してTypeScriptが導入しやすいReactで、TypeScriptを前提としたプロジェクトを作成します。

環境

$ node --version
v14.15.0
package.json
{
...
  "dependencies": {
    "next": "10.0.3",
    "react": "17.0.1",
    "react-dom": "17.0.1"
  },
  "devDependencies": {
    "@types/node": "^14.14.10",
    "@types/react": "^17.0.0",
    "typescript": "^4.1.2"
  }
}

React のプロジェクトを作る

こちらは TypeScript を使うオプションがあるので使っていきましょう。

 npx create-react-app --template typescript .

Next.js のプロジェクトを作る

create-react-app のようにプロジェクト立ち上げから TypeScript に対応するテンプレートは用意されていません。
なので、プロジェクトを作った後は自分でTypeScriptの設定を追加します。

npx create-next-app .

次にTypeScriptで使うためのパッケージを導入します。

yarn add --dev typescript @types/node @types/react @types/react-dom

このパッケージを導入しないと yarn dev したときに失敗します。

It looks like you're trying to use TypeScript but do not have the required package(s) installed.
.
Please install @types/node by running:

    yarn add --dev @types/node

If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).

ページを構成するファイルも jsx から tsx に変更します。

  • ./pages/_app.js -> ./pages/_app.tsx
  • ./pages/index.js -> ./pages/index.tsx
  • ./pages/api/hello.js -> ./pages/api/hello.ts
    APIは ts にする

APIのサンプルには型をつけます。APIを作りこむのはまたの機会にしましょう。

pages/api/hello.ts
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { NextApiRequest, NextApiResponse } from "next";

export default (req: NextApiRequest, res: NextApiResponse) => {
  res.statusCode = 200
  res.json({ name: 'John Doe' })
}

この状態で yarn dev を実行してdevelopment用のサーバーを立ち上げるとTypeScriptを使うようになります。
tsconfig.jsonyarn dev を実行したときに自動生成されます。

We detected TypeScript in your project and created a tsconfig.json file for you.

おまけ: Reactのページ(コンポーネント)をNext.jsに移植する

Reactのclassで作ったコンポーネントはをそのまま Next.js の pages に移植すると動作します。

例えば create-react-app で生成されたサンプルもほぼそのまま移植することができますが、
外部ファイルとしてCSSや画像が配置されているので これを解決します。

react/src/App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

CSSに関してはtsxに書かれているままの記述でインポートできないため、Nextの _app.tsx に追記します(グローバルで適用されれます)

next/pages/_app.tsx
import '../styles/globals.css'
import '../styles/react.css'  // ./src/App.css

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

error - ./styles/react.css
Global CSS cannot be imported from files other than your Custom . Please move all global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://err.sh/next.js/css-global

logo.svgは public に移動させます。また、 import logo from './logo.svg'; は使えないので、 img タグの src はWebに公開した時の絶対パスを指定します。

Nextに移植したコンポーネントはこんな感じです。

next/pages/react.tsx
import React from 'react';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src="/logo.svg" className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

また、classの形で書いたReactコンポーネントもNext.jsで動作するようです。
例えばこのようなReactコンポーネントも同様にNextのpagesに配置すると動作します。
(簡単なサンプルで試したので、複雑なコンポーネントではうまくいかないかもしれません)

react/src/Sample.tsx
import React, { Component } from 'react';

type Props = { ... }
type State = { ... }

class App extends Component<Props, State> {
  constructor(props: Props) {
    super(props)
    ...
    }

  render() {
    return (
     ...
    );
  }
}

export default App;

Nuxt.jsの pages にVueのコンポーネントを移植した時と同じような感触ですね!

参考

Reactの環境構築 — 仕事ですぐに使えるTypeScript ドキュメント
https://future-architect.github.io/typescript-guide/react.html#next-js

Next.jsとTypeScriptでアプリを作る - Qiita
https://qiita.com/kojiro_ueda/items/a490f5dfc77f5f89ecbd#2-webapi%E3%82%82%E4%BD%9C%E3%81%A3%E3%81%A6spa%E3%81%8B%E3%82%89%E5%8F%A9%E3%81%91%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B

19
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16