react-collapsibleを使ってアコーディオンを作成する

アコーディオン、Webでよく見かけますよね。
今回はreact-collapsibleを使用してFAQのようなアコーディオンを作成してみようと思います。

完成形

最初に完成形だけ置いときます。
f:id:sho03:20210220172807g:plain
とりあえずソースを見せろという方はこちらをご覧ください。

準備

まずは必要なパッケージのインストール

yarn add react-collapsible

簡単な例

1番単純な例を作成します。

import Collapsible from "react-collapsible";

export function AccordionSample() {

  return <Collapsible trigger={"click me!!"}>
      This is easiest Accordion!!
    </Collapsible>
}

f:id:sho03:20210220161322g:plain
上記のようなコンポーネントを作成することで、click me!!!の文字をクリックするとその下部にhello, collapsible!が出力されるのがわかると思います。

Collapsibleのオプション

Collapsibleアコーディオンの開閉を制御するtriggerオプションが必須になりますが、それ以外にもいくつかのオプションがあります。
すでに使用したtriggerオプションも含めていくつか紹介しようと思います。

アコーディオンの開閉動作に関わるオプション

trigger

アコーディオンの開閉のトリガー(契機)となる文字列またはReactNodeを指定します。前述した例では文字列を指定しましたが、ReactNodeを渡せるので、任意のコンポーネントも使用できます。

<Collapsible trigger={<AnyComponent/>}>
</Collapsible>

transitionTime

アコーディオンの開閉にかかる時間を指定します。単位はミリ秒です。
transitionTime={1000}

transitionCloseTime

アコーディオンが閉じる時の時間を指定します。transitionTimeと同様に単位はミリ秒です。
transitionCloseTime={1000}

アコーディオンのスタイルに関わるオプション

className

アコーディオンが閉じている時に適用されるCSSスタイルを指定します。なお、

openedClassName

アコーディオンが開いている時に適用されるCSSスタイルを指定します。

感想

かなり簡単にアコーディオンが実現できるので、今回作成したようなアコーディオンを作るには便利に感じました。

参考

公式ドキュメント

typed-css-modulesを使用して型定義ファイルを作成する

この記事の目的

typed-css-modulesをインストールし、*.module.css.d.tsファイルが自動作成されるようにする。

はじめに

ReactにはCSS modulesという機能があり、これを使用するとコンポーネントCSSファイルを1対1で紐付けられるようになります。例えば、

export function Sample() {
  return <div>
    <h1>hello, world</h1>
  </div>
}

このようなコンポーネントに対して、Sample.module.cssというファイルを作成すると、コンポーネント側ではimport classes from "Sample.module.css"とすることでコンポーネントのスタイル指定をclassName={classes.container}などといったようにできるようになります。

本題

はじめにで述べたように、モジュールとスタイルシートを1対1で紐づけることができます。そこからさらに一歩進んで、TypeScriptの型定義ファイルにスタイルのクラスを定義できるようにします。

typed-css-modulesをインポート

まずは必要となるtyped-css-modulesをインポートします。

npm install -g typed-css-modules

次に、インストールしたtyped-css-modulesのコマンドを実行し、*.module.cssファイルに対する型定義ファイルを作成します。

tcm src

上記のsrc*module.cssファイルが存在するディレクトリを指定します。

ここまでできると、*module.cssファイルと同じディレクトリに*module.css.d.tsファイルが作成されているはずです。

終わりに

上記までの方法だと毎回tsm srcを実行しないといけないので、package.jsonのscriptsをうまいこと修正すればいいはず。

first-childが効かなかったので

first-childが効かない時の対処方法。

first-childが効かない例

例えば以下のようなHTML構造になっている場合、

<div class="myClass">
  <h1>title</h1>
  <p>hoge</p>
  <p>hoge</p>
  <p>hoge</p>
</div>

以下のようなCSSは適用されません。

.myClass p:first-child {
  background-color: red;
}

これは、myClassの最初の子要素がpではなくh1要素であるためです。

修正方法

要は、ある要素の中で1番目の要素にすればいいわけです。なので、

<div class="myClass">
  <h1>title</h1>
  <div>
    <p>hoge</p>
    <p>hoge</p>
    <p>hoge</p>
    <p>hoge</p>
  </div>
</div>

こんな感じでしょうか。
ただし、この方法ではHTMLの構造が変化してしまいますので、そこはいろいろ調整する必要はありますのでご留意ください。

npmってなんですか?

npmってなんですか?

とりあえず、「what is npm?」でググってみました。
what is npm?

世界一大きいソフトウェアライブラリ

  • npmは世界で最も大きいソフトウェアライブラリです。
  • 800000以上のパッケージが登録されています。
  • OSS開発者は開発したソフトウェアをシェアするためにnpmを使用しています。
  • たくさんの団体が開発の管理にnpmを使っています。

ソフトウェアパッケージマネージャー

  • npmはNode Package Managerの略です。
  • 全てのnpmパッケージはpackage.jsonというファイルで管理されます。
  • package.jsonJSON形式で記述されなければなりません。
  • package.jsonには最低限nameversionの情報がなければなりません。

多分、イメージとしてはJavaでいうgradleやmavenRubyのgemみたいなもの・・かな?

npmを使ってみる

どんなものなのかを知っただけではその技術や知識を身につけたとは言えません。
ので、実際にnpmのコマンドを叩きつつ学んでいきたいと思います。
なお、 こちら が本家のドキュメントになりますが、見ての通りたくさんのコマンドがありますので個人的によく使うコマンドに絞って紹介していきます。

npm init

npm initは、npmの初期化コマンドです。
npm initを実行するとpackage.jsonが作成されます。
なお、実際にコマンドラインnpm initを実行すると、packge nameversionなどを聞かれますが、わからなければひたすらEnterキーを連打すれば大丈夫です。
最後に、Is this OK? (yes)という表示が出たら、yesとタイプしてEnterを押せば完了です。
ここまで完了すると以下のようなファイルが作成されていると思います。

{
  "name": "javascript",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

なお、一番上の"name":"javascript"については、npm initを実行したディレクトリの名前となりますので、実行環境によって差異が発生します。

オプション

一応オプションです。

-- y

後出しになりますが、npm init --yとすれば上記の質問は全てスキップされます。
(全て単にEnterを押した時と同じ挙動になります。)

npm install

それではpackage.jsonができたところで実際に何かパッケージをインストールしてみましょう。

基本の使い方

npm install <package name>
の形式で、<package name>にはインストールしたいパッケージ名を入力します。例えば、

npm install lodash

とすると、lodashというパッケージがインストールできます。 インストールが完了すると、package.jsonに下記のような追記がされます。

  "dependencies": {
    "lodash": "^4.17.20"
  }

また、package.jsonと同じディレクトリに、node_modulesというディレクトが作成され、以後npm installされたパッケージはこのディレクトリに追加されていきます。

オプションなど

--save-dev

--save-devを付けると、develop環境のみで使用可能な状態となるようパッケージがインストールされます。
実際に、npm install lodash --save-devと実行すると、

  "devDependencies": {
    "lodash": "^4.17.20"
  }

このように、dependenciesではなくdevDependenciesにインストールされていることがわかります。 *1

-g

-gをつけるとグローバルインストールとなります。

npm install lodash -g

グローバルにインストールされると、どこでもこのパッケージが使用できるようになります。
ただ、一般的にプロジェクトで使用するだけのパッケージはグローバルインストールしない方がいいでしょう。
他方で、例えばコマンドラインをインストールする(今回のnpmコマンドなど)はグローバルインストールするのが良いかと思います。

パッケージを指定しない場合

単に、

npm install

とすることもできます。
この場合、そのプロジェクトに必要な・・言い換えるとpackage.jsonに記述されている各種パッケージがインストールされます。
例えば、チーム開発をしている場合に他の方がパッケージを追加し、package.jsongithubなどの共有リポジトリにあげた後などに使用するかと思います。

エイリアス

  • npm i
  • npm add

最後にエイリアスも紹介しておきます。
エイリアスとは別名のことです。つまり、

npm install lodash
npm i lodash
npm add lodash

上記の3つのコマンドは全て同じ意味になります。

npm uninstall

npm uninstallは、コマンド名の通り、パッケージのアンインストールを行います。

基本の使い方

npm uninstall lodash

もし、「このパッケージ不要だな」と思ったらこちらのパッケージを使用しましょう。
間違っても、node_moduleディレクトリから直接削除しないように。
npm uninstall lodashを使用すれば安全にアンインストールができます。

オプション

--save

dependenciesからパッケージを削除します。

--save-dev

devDependenciesからパッケージを削除します。

--save-optional

optionalDependenciesからパッケージを削除します。

--no-save

pakcage.jsonファイルからは該当パッケージを削除しません。
→node_modulesディレクトリからは削除されますが、package.jsonには残ったままになります。(どういうシーンで使うのかはよくわかりません。 )

npm update

npm updateを使用すると、インストール済みのパッケージをアップデートすることができます。

npm update <package_name>

特定のパッケージをアップデートする場合は上記のコマンドを実行します。
また、下記のように特にパッケージを指定しなければ、全てのパッケージがアップデートされます。

npm update

npm help

ヘルプを見ることができます。 特定のコマンドのヘルプを見る場合はnpm <command> -hとします。

npm install -h

気になったエラー(ワーニング)

npm WARN <name@version> No repository field.

以下を追加することで解消されました。

  "repository": {
    "private": true
  }

この記事が参考になります。)

終わりに

とりあえず、基本的な使い方として、init install uninstallをまとめてみました。
他にもたくさんのコマンドがあるので、使う機会があれば適宜記事にしたいと思います。

参考

*1:dependenciesとdevDependenciesについてはそのうちまとめます。

オリジンってなんですか?

弁当ですか?(違う)

結論

一言で言うと、プロトコルドメイン・ポートまでを一塊にしたもの。

解説

例えば、

http://example.com:80/app1/index.html

上記のようなURLがある場合に、

http://example.com:80

ここまでがオリジンということになります。
あえて分解する必要もないのですが、
プロトコルhttp
ドメインexample.com
ポートが80
になります。

オリジンが話題になるのは、同一オリジンポリシーなどが問題になる場合ですが、ここでは割愛します。

参考

useStateに型情報を付与する

useStateに型情報を付与する

TypeScript + Reactでフロントエンド開発するなら、最大限型による恩恵は受けたいですよね。
ということで、以下のようにすると型情報を付与したuseStateが定義できます。

booleanなどの場合

この場合は型推論が働く(多分)のでここまで明示する必要はないかもですが。

const [hoge, setHoge] = useState<boolean>(false);

配列の場合

booleanなどを使用する場合は型推論が働くと思うので問題ないかと考えているのですが、配列などを扱う場合は型を明示した方が良さそうです。

const [names, setNames] = useState<string[]>([]);

スプレッド構文

JavaScriptでたびたび見かけるスプレッド構文についてまとめます。

構文

...obj; // こういう感じ

配列の場合の例

const arr = [1,2,3,4,5];
const arr2 = [...arr, 6,7,8];
console.log(arr2); //[1, 2, 3, 4, 5, 6, 7, 8]

オブジェクトの場合の例

const user = {
  name: "taro",
  age: 20
}

const user2 = {
  ...user
}

console.log(user2);
//結果(userオブジェクトと同じになる)
{
name:"taro",
age:20
}

配列にしてもオブジェクトにしても、スプレッド構文を使用した変数が展開されるイメージを持つのがいいのかもしれない。

オブジェクトは特定の変数を上書きできる。

例えば以下のようにすると、

const user = {
  name: "taro",
  age: 20
}

const user2 = {
  ...user,
  age: 30
}
console.log(user2);
//こうなる
{
name:"taro",
age:30
}

プロパティnameは元のuserオブジェクトを引き継いでおり、ageプロパティだけ新しく定義されているのがわかる。

分割代入

スプレッド構文の親戚みたいなものか。

const arr = [1,2,3];
const [a, b, c] = arr;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3

const obj = {
  color: "red",
  animal: "fox",
  kind: "udon"
}
const { color, ...rest } = obj;
console.log(color);
console.log(rest);
// 結果
red
{
animal:"fox",
kind:"udon"
}

まとめ

使えるようになると便利