(私的に)Reactで開発に役立ったツールやライブラリ

この記事はフラー[Advent Calendar 2019](https://adventar.org/calendars/4155)の13日目の記事です。
前日の12日目は[@shmokmt](https://shmokmt.github.io/)で、[コマンドラインのオプションの設計について](https://shmokmt.github.io/post/2019/12/cli-design/)でした。

私は今年の4月からウェブフロントエンジニアとして、JavaScriptを書いています。
最初はVue.jsやWordPressを触ってきましたが、なんやかんやあって8月ごろからReactを使うことになりました。
Reactは全くわからなかったので、どんなライブラリを使って開発していいかわかりませんでした。
しかし、先輩エンジニアの方から色々と教えてもらって、なんとか今開発を進められている状況です。
今回はその中で、今までに使ってみてよかったツールやライブラリをまとめていきます。

##redux-devtools-extension
このツールはReduxを使う上で便利なツールです。
どの状態からどの状態へ変化したかを知ることができるので、デバッグに役立ちます。
例えば、下のコードのようなカウンターアプリを作ったとします。


``` counter.ts
const initialCounterState = {
  count: 0
};

export const counterReducer = (state = initialCounterState, action: any) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    case "DECREMENT":
      return { count: state.count - 1 };
    default:
      return state;
  }
};

export const increment = () => ({
  type: "INCREMENT"
});

export const decrement = () => ({
  type: "DECREMENT"
});
```
```Counter.tsx

const Counter: React.FC = () => {
  const count = useSelector<any, any>(
    ({ counterReducer }) => counterReducer.count
  );
  const dispatch = useDispatch();

  return (
    <div>
      <div>{count}</div>
      <div>
        <button onClick={() => dispatch(increment())}>+</button>
        <button onClick={() => dispatch(decrement())}>-</button>
      </div>
    </div>
  );
};
```

このアプリにredux-devtools-extensionを使うと、下の図のようにdispatchされたアクションとアクションの前後でどのように状態が変化したか把握できます。
また、アクションがdispatchされた時の状態に戻すことができるjump機能やdispatchされたアクションをなかったことにできるskip機能があるので、どのアクションでバグが起きたかを捕まえやすくなります。

<img width="1438" alt="スクリーンショット 2019-12-12 23.07.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540090/125e1765-935e-5563-8451-dea5274f9172.png">

肝心の導入の仕方ですが、storeの作成時に `createStore()` の引数に`window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()` と入れるだけです。
より詳しい情報は[github](https://github.com/zalmoxisus/redux-devtools-extension)の方をご覧ください。

```typescript
const store = createStore(
  rootReducer,
  (window as any).__REDUX_DEVTOOLS_EXTENSION__ &&
    (window as any).__REDUX_DEVTOOLS_EXTENSION__()
);
```


##styled-components
こちらはCSS in JSのライブラリで、javaScriptを使ってCSSを書くことができます。
このライブラリのいいところは、CSSの影響範囲を狭めることができることです。
これ以上うまい説明ができないので、実際の例を作りました。
例えば、下のような表示をしたいときに、`App.tsx`と`Sample.tsx`を作ったとしましょう。
<img width="441" alt="スクリーンショット 2019-12-13 0.05.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540090/0a1c21bf-5788-9d67-48d6-70de9d264b08.png">

```App.tsx
import "./App.css";
import Sample from "./Sample";

const App: React.FC = () => {
  return (
    <div>
      <p className="red">App component</p>
      <Sample />
    </div>
  );
};
```

```App.css
.red {
  color: red;
}
```

```Sample.tsx
import "./Sample.css";

const Sample: React.FC = () => {
  return <p className="red">sample component</p>;
};

```
```Sample.css
.red {
  background-color: red;
}
```

しかし、実際にアプリを立ち上げて見てみると、下のように文字と背景が赤色になってしまいます。
<img width="406" alt="スクリーンショット 2019-12-13 0.00.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540090/4abe60fa-138a-23af-36c9-4b75a3962f18.png">
これはCSSに名前空間がないことが原因です。
簡単にいうとCSSファイルを分けていてもクラス名が同じであれば、全ての同じクラス名がついている要素にスタイルが適用されてしまうということです。

しかし、styled-componentを使って`App.tsx`と`Sample.tsx`を下のように書き換えてあげることで、この問題を回避できます。
（BEMやSMACSSなどのように命名で解決する方法もありますが、ここでは割愛します。）

```App.tsx
import styled from "styled-components";
import Sample from "./Sample";

const App: React.FC = () => {
  return (
    <div>
      <StyledP>App component</StyledP>
      <Sample />
    </div>
  );
};

const StyledP = styled.p`
  color: red;
`;
```

```Sample.tsx
import styled from "styled-components";

const Sample: React.FC = () => {
  return <StyledP>sample component</StyledP>;
};

const StyledP = styled.p`
  background-color: red;
`;

```
こうすることによって、コンポーネントごとにCSSの名前空間を分けることができます。
時間がない中で開発するにあたって、簡単に狙った場所だけにスタイルを当てることができるので本当に助かってます。
（ただし、適当に命名するとぱっと見でどんなコンポーネントか分からなくなるのでご注意を......）


##終わりに
ということで教えてもらったいいツールを紹介しました。
特にstyled-componentは開発のレビューで教えてもらって、今ではなくてはならないものとなってます。
redux-devtools-extensionは教えてもらって今回初めて使いましたが、とても使いやすいので取り入れていこうと思います。
今回紹介したものは教えてもらったものの一部で、他にも`immer`などを教えてもらいましたが、まだまだ触れていない状況です。
早く触れるようにならなければ......。