20200219のReactに関する記事は5件です。

Reactアプリのデバッグ方法

この記事の目的

Reactの公式ページを見たがReact DevToolsを用いたデバッグ方法についての記述が無かったため(パフォーマンス最適化の項でDevToolsの紹介はあった)、Reactアプリのデバッグを行う上で最低限知っておくべき内容を整理しておく。

参考資料

公式ガイド

Reactアプリのデバッグ方法

準備

Reactアプリのデバッグはブラウザで行う。FirefoxとChromeのどちらでもデバッグ用の拡張機能(React Developer Tools)が用意されているので、普段Webアプリのデバッグで利用しているブラウザ向けのDevToolsをインストールして利用する。

ChromeのReact Developer Tools
FirefoxのReact Developer Tools

※IE用は存在しないので、IEでのデバッグは諦めてください。。。

React DevToolsの使い方概要

この資料ではChromeのDevToolsで説明する。(FirefoxのDevToolsでも基本同じはず)

アイコンの見方

ChromeのReact DevToolsをインストールすると、ブラウザの右上にReactのアイコンが表示される。
アイコンの色によって意味が異なり、以下の3種類が存在する。

アイコンの種類 image.png image.png image.png
Reactで描画されたページか否か ×(Reactで描画されたページではない) ○(Reactで描画されたページ) ○(Reactで描画されたページ)
Reactのビルドモード - Production Build Development Build
React DevToolsによるデバッグ - 不可 可能

自分が作成したReactアプリをnpm startで起動してWebページを開いた場合、一番右の赤色アイコンが表示される。

画面のコンポーネント構成を見る方法

「Chromeのメニュー」→「その他ツール」→「デベロッパーツール」を開く。
デベロッパーツールのタブメニューから「Components」を選択。
image.png

現在ブラウザで表示しているページのコンポーネント構成を確認できる。
また、対象のコンポーネントをクリックすればpropsやstateの値を確認することも可能。
image.png
多重階層になっていてお目当てのコンポーネントを探すのが大変なときは、Componentsタブ内の左上にある矢印ボタンを押して画面から対象コンポーネントを選択することも可能。
(ネストされたコンポーネントを正確にポインティングするのは難しいようなので、補助的に使ってあげてください)

ブレイクポイントを設定してステップ実行でデバッグする

React Developer ToolsでComponentsタブを開き、ブレイクポイントを設定したいコンポーネントを選択した状態で「<>」アイコンをクリックする。
image.png

コンポーネントのソースがReact Developer Toolsに表示されるので、ブレイクポイントを設定したい行番号をクリックする。ブレイクポイントを設定した行番号は緑色になる。
image.png
ブレイクポイントを設定した状態でWebブラウザ内でReactアプリを操作すると、ブレイクポイントで処理が止まる。ブレイクポイントで処理が止まると、対象の行が緑色で網掛けされる。
image.png

ブレイクポイントで処理が停止したら、以下のいずれかの実行が可能。
image.png

  • Resumu script execution
    • ブレイクポイントからそのまま処理が続行される
  • Step over next function call
    • ステップオーバーで実行
    • 今いる関数内の処理はすべて実行し、次の関数が呼ばれたタイミングで処理をブレイク(停止)する
  • Step into next function call
    • ステップインで実行
    • 今いる関数から別の関数が呼ばれるタイミングまで処理を進め、別の関数に入ったタイミングで処理をブレイク(停止)する
  • Step out of current function
    • ステップアウトで実行
    • 今いる関数内の処理はすべて実行し、今いる関数の呼び出し元に戻ったタイミングで処理をブレイク(停止)する
  • Step
    • 一行づつ順番に実行する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React Routerのざっくり概要

この記事の目的

公式ページのガイドを見てもらうのが一番だが、公式は英語の情報しかないためReact Routerを使用するにあたって押さえておきたいポイントをかいつまんで説明する。

参考資料

公式ガイド

React Routerのざっくり概要

React Routerとは

ReactでSPA(Single Page Application)を実現し、SPAのルーティングを管理するためのモジュール。
Reactのルーティングライブラリは過去にいくつか出ては消えてを繰り返してきたが、現在はReact Routerがデファクトスタンダードと言える。

基本的な使い方

画面の構成例

Material UIのテンプレートページで紹介されている、以下の画面構成を例にReact Routerの使い方を説明する。

image.png

画面の構成例をコンポーネント単位に分解

上記の画面は、コンポーネント単位に分解すると以下のような構成となる。

image.png

左端のDrawerコンポーネントにメニューがあり、メニューを選択するとmainタグの領域にコンテンツを表示する。
このとき、ページ遷移(HTMLのhttpリクエスト・レスポンス)は発生せず、DrawerコンポーネントとAppBarコンポーネントの表示はそのままにmain領域のコンテンツだけを入れ替える動作となる。

ページ遷移(HTMLのhttpリクエスト・レスポンス)を行わないでコンテンツの入れ替えを行うので、SPA(Single Page Application)となっている。

React Routerをコードに仕込む例

上記の画面例をReact Routerで実現する場合のコード例を示す。

コードの例

app.tsx
// ※説明に必要なステップ以外は省略している

import React from "react";
import Dashboard from "./components/Top";
import About from "./components/About";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";  //ポイント1

const App: React.FC = () => {
  return (
    <Router>  //ポイント2
      // AppBar
      <AppBar>
      </AppBar>
      // Drawer
      <Drawer>
        <List>
          <ListItem button component={Link} to={/}>  //ポイント3a
            <ListItemText primary="Dashboard" />
          </ListItem>
        </List>
        <List>
          <ListItem button component={Link} to={/about}>  //ポイント3b
            <ListItemText primary="About" />
          </ListItem>
        </List>
      <Drawer>
      // main
      <main>
        <Switch>  //ポイント4a
          <Route exact path="/">  //ポイント4b
            <Dashboard />
          </Route>
          <Route exact path="/about">  //ポイント4c
            <About />
          </Route>
        </Switch>
        <main>
    </Router>
  );
};

export default App;

注目すべきポイント

ポイントは以下の4点。

  1. react-router-domをインポートする
  2. メニュー領域(この例の場合Drawerコンポーネント)とコンテンツ領域(この例の場合はmainタグ)を<Router>タグで囲む(Routerコンポーネントの一部として扱われる)
  3. メニュー領域(Drawerコンポーネント)
    1. メニューから「Dashboard」を選択した場合、/にルーティングすることを定義している
    2. メニューから「About」を選択した場合、/aboutにルーティングすることを定義している
  4. コンテンツ領域(mainタグ)
    1. コンテンツを表示する領域を<Switch>タグで囲む(Switchコンポーネントの一部として扱われる)
    2. <Route>タグでルーティングを定義する。この場合、/にルーティングしたらmainタグの領域にDashboardコンポーネントを表示するように定義している
    3. <Route>タグでルーティングを定義する。この場合、/aboutにルーティングしたらmainタグの領域にAboutコンポーネントを表示するように定義している

応用的な使い方

イベント起因でルーティング

基本的な使い方では、Linkコンポーネントを使ってボタンを押したらルーティングする方法を取ったが、ルーティングHistoryに直接パスを追加するとこでonClickイベントなどのイベント起因でルーティングすることも可能。

コードの例

order.tsx
// ※説明に必要のないステップは省略している

import React from "react";
import { withRouter } from 'react-router';  //ポイント1

class Orders extends React.Component {
  routingToAbout = () => {
    this.props.history.push('/about')  //ポイント3
  }

  render() {
    return (
      <div>
        <Button onClick={this.routingToAbout}> //ポイント2
          aboutへ移動
        </Button>
      </div>
    )
  }
}

export default withRouter(Orders)

注目すべきポイント

ポイントは以下の3点。

  1. インベント起因のルーティングではwithRouterコンポーネントを使用するので、'react-router'をインポートする
  2. onClickイベントでルーティングしたいので、onClickイベントが発火したらコンポーネント内の関数を呼ぶように設定する
  3. onClickイベントから呼ばれた関数内では、this.props.history.push('/about')でルーティングHistoryにaboutページへのルーティングを追加する。これによって、ルーティングHistoryの最後がaboutページになるので、aboutページに遷移することになる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

create-react-appが公式にreduxテンプレートを公開した件

Reactを触ったことがあるみなさんならご存知のcreate-react-appですが、公式にReduxのテンプレートを公開したようです

使い方は簡単
npx create-react-app {app_name} --template redux
templateにreduxをしてあげるだけで使えちゃいます

通常のcreate-react-appとの差分

普通のcreate-react-appコマンドで作成したときと何が違うのか一部抜粋してみました

まずは起動してみると...

redux templateトップページ

カウンターアプリのサンプルが表示されていますね

package.json

通常のcreate-react-appから追加でインストールされているモジュールは

  • @reduxjs/toolkit
  • react-redux

の2つでした

ディレクトリ構造

src以下のディレクトリ構造は以下のようになっています

src
├── App.css
├── App.js
├── App.test.js
├── features
│   └── counter
│       ├── Counter.js
│       ├── Counter.module.css
│       └── counterSlice.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
├── setupTests.js
└── store.js

大きな違いとしては、カウンターのサンプルがfeatures以下に作成されています

また、storeが始めから作成してあり、index.jsProviderに既に登録されています

src/index.js
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

カウンターアプリも含め基本的に全てHooksFunctional Componentで書かれていました

typescript対応

現在はまだ公式からtypescriptに対応したものは公開してないようです
でも近いうちに公開されるはず...

補足ですが、
npx create-react-app {app_name} --typescript
は廃止予定らしいので
npx create-react-app {app_name} --template typescript
を利用しましょう

リンク

github release note
https://github.com/reduxjs/cra-template-redux/releases/tag/v1.0.0

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Next.js で node-sass の代わりに dart-sass を使う

はじめに

Node.js のバージョンの違いとかでエラーを吐いちゃう node-sass に疲れたので、dart-sass を Next.js で使う方法を書いていきます。node-sass と dart-sass の違いについては本記事では触れません。

環境

  • Next.js 9.2.2
  • Node.js 12.16.0

インストール

npm i -D @zeit/next-sass sass fibers

上記の sass が dart-sass になります。また fibers と組み合わせることでパフォーマンスの改善になるみたいなので入れておきましょう。詳しくは GitHub: sass/dart-sass で。

@zeit/next-sass と sass-loader で node-sass が入ってないよって警告が出るかとは思いますが、とりあえず素直に受け入れて、今は無視しておきましょう。

設定

next.config.js
const withSass = require("@zeit/next-sass");

module.exports = withSass({
  cssModules: true,
  sassLoaderOptions: {
    implementation: require('sass'),
    sassOptions: {
      fiber: require('fibers')
    }
  }
});

module.exports = {
  experimental: { scss: true }
};

experimental 部分は Next.js 9.2 で導入された Built-In CSS Module Support for Component-Level Styles を scss で書けるようにするための記述なので、無視してかまいません。

まとめ

特に node-sass で問題ないのなら dart-sass に乗り換える必要もないのかなとは思いますが、疲れを感じたら dart-sass という選択もアリかなと、導入して思いました。

リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】TypeError: Cannot read property '***' of undefined の対処法

今回は練習のためにreactでTodoリストを作成していた時にハマったエラーと対処法をメモしときたいと思います。

TypeError: Cannot read property '***' of undefined

これはリストの削除機能を作る時にハマりました。

そのまま翻訳すると「未定義のプロパティ「***」を読み取れません」といった感じなんですが、これはちゃんと定義されていないことが問題なようなのでアロー関数で書いてあげれば治りました。

test.js
removeTask(text){
        var updatedTasks = this.state.tasks;
        updatedTasks.splice(updatedTasks.indexOf(text), 1);
        this.setState({tasks: updatedTasks});
}

これを以下に変更。

test.js
removeTask=(text)=>{
        var updatedTasks = this.state.tasks;
        updatedTasks.splice(updatedTasks.indexOf(text), 1);
        this.setState({tasks: updatedTasks});
}

こんな感じでちゃんと渡してあげたらスッと治りました。

Cannot read property 'map' of undefined

このエラーはほとんど普通にタイプミスです。
私の場合は「var tasksList=[];」を「tasks=tasksList」に定義し直していたのを忘れて「tasksList」で進めてしまっていたのでエラーが出たといった感じでした。

まとめ

どちらもしょうもないミスなんですが、結構ハマった時間が長かったのでもし困っている方の助けになれたら嬉しいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む