【React・TypeScript】コーディングルールの備忘録

# はじめに
最近プロジェクトにてReact、TypeScriptを触っているのですが、コーディングする上でのそれぞれのお作法的なところを理解していなかったので、個人的に参考になった記事から抜粋させてもらい備忘録としてまとめました。
現状探り探りで試しているため、今後も随時更新していこうと思います。
# コーディングルール
## AND/OR文はReactと相性良い。
短い命令はコンポーネント記述内に綺麗に収まります。ただし、三項以上は逆に見えづらくなるので注意。
#### AND: 変数に値が存在するか確認して代入したいとき
```tsx:Bad
if (response) {
  text = response.text;
}
```
```tsx:Good
const text = response && response.text;
```
### OR: 変数に値が存在するとき代入したいとき
```tsx:Bad
if (temp) {
  text = temp;
} else {
  text = 'textは存在しません';
}
```
```tsx:Good
const text = temp || 'textは存在しません';
or
// Null合体演算子
// undefinedとnull以外のfalsyな値(0や"")を許容したい時に||を使う場合右辺値となる
const text = temp ?? 'textは存在しません';
```
## オブジェクトは使いこなせているか
複数の分岐でコンポーネントを分けるときに便利です。
```tsx:Bad
switch (user.type) {
  case user:
    return <User />;
  case admin:
    return <AdminUser />;
  case host:
    return <HostUser />;
}
```
```tsx:Good
const userView = {
  user: <User />,
  admin: <AdminUser />,
  host: <HostUser />,
};

return userView[user.type];
```
## useEffect 内で複雑な処理を記述しない
useEffectの中に処理を大量に記述する方法は避けたい方がいいです。上記のDo ActionAたちは一行なので、目立っていませんが、もし、20行、30行である場合、どこまでが useEffect の範囲かわからなくなってしまいます。
そのため、メソッドとして切り分け、 useEffect 内でそのメソッドを呼び出す形がよいかと考えます。
```tsx:Bad
const hoge = () => {

　　useEffect(()=>{
   // Do ActionA
   // Do ActionB
   // Do ActionC
 },[])
}
```
```tsx:Good
const hoge = () => {
  const actionA = () => {
    // Do ActionA
  }
  const actionB = () => {
    // Do ActionB
  }
  const actionC = () => {
    // Do ActionC
  }
  useEffect(()=>{
    actionA();
    actionB();
    actionC();
  },[])
}
```
## useEffectは複数書いても良い
無理に一つのuseEffectの中に書く必要はありません。行数が多くなる場合はuseEffectがどこまで影響しているのか分かりやすいように分けたほうがいいです。
```tsx:Bad
useEffect(() => {
  const getApi1 = async () => {
    const response = await api('classinfo');
    命令1(response);
  };

  const getApi2 = async () => {
    const response = await api('userinfo');
    命令2(response);
    命令3(response);
  };
  getApi1();
  getApi2();
}, []);
```
```tsx:Good
// 1つ目
useEffect(() => {
  const getApi = async () => {
    const response = await api('classinfo');
    命令1(response);
  };
  getApi();
}, []);

// 2つ目
useEffect(() => {
  const getApi = async () => {
    const response = await api('userinfo');
    命令2(response);
    命令3(response);
  };
  getApi();
}, []);
```
## <>JSX部分</>に集中できる構成になっていること
JSX部分は、リリース後も変更機会が多いので、運用・保守しやすいように、「類似コードを使い回すデータ取得」と「オリジナルが多い重要な部分」は切り離されるべきです。
```tsx:Bad
// 重要な部分が直感的に把握できない
const Area = () => {
  const [user, setUser] = useState();
  // ここの記述が多いからここが一番重要か?
  useEffect(() => {
    const fetchUser = async (): Promise<void> => {
      const response = await GetUser();
      setUser(response);
    };
    fetchUser();
  }, []);
  // ここまでのデータの流れを把握するのに時間がかかる
  return <>{user.name}</>;
};
```
```tsx:Good
// 「データ取得」と「状態管理/デザイン」の分離
const useUser = (): User | undefined => {
  const [user, setUser] = useState<User>();
  useEffect(() => {
    const fetchUser = async (): Promise<void> => {
      const response = await GetUser();
      setUser(response);
    };
    fetchUser();
  }, []);

  return user;
};

// データの表示のコンポーネント
const Area = () => {
  const user = useUser();
// 直感的に重要な部分に集中できる
  return <>{user?.name}</>;
};
```
## オプショナルに対して、デフォルト引数は使用できているか
想定外の挙動にならないように、undefinedで処理しません。
```tsx:Bad
type Props = {
  name: string;
  isDisplayNone?: boolean; // オプショナルのプロップス
};

//undefined=falseで処理
const UserCard: FC<Props> = ({ name, isDisplayNone }) => (
  <div style={{ display: isDisplayNone ? 'none' : 'block' }}>{name}</div>
);
```
```tsx:Good
type Props = {
  name: string;
  isDisplayNone?: boolean; // オプショナルのプロップス
};

// undefinedの時はfalseと明示する
const UserCard: FC<Props> = ({ name, isDisplayNone = false }) => (
  <div style={{ display: isDisplayNone ? 'none' : 'block' }}>{name}</div>
);
```
## 配列に対して「itemList」は使用しないで、「items」を使用する
List というのは、プログラムにおいて特別な意味があります。（例：Java の List インターフェースなど）そのような重要な単語を変数名に使用すると、誤解を生む可能性があります。
そのため、~Listではなく~sなどを使用した方がよいと考えています。
```tsx:Bad
const followerList:User[]  // NG　~Listを使用する
```
```tsx:Good
const followers:User[]  // OK　~sを使用する
```
## elseがない場合は即returnする
無駄にコードを追う必要がないようすぐにreturnで返したほうがいいです。
```tsx:Bad
const hoge = () =>{
  if(foo === "bar"){
    // Do Something
  }
}
```
```tsx:Good
const hoge = () =>{
  // 条件式を逆にし、即 return する
  if(foo !== "bar") return;
  // Do Something
}
```
## (!hoge)は使用しない
!(hoge) の場合、hoge が false の場合はもちろん、 null や undefined の場合も、条件が一致していると判断してしまいます。
そして、意図せず通過した hoge が処理内で問題を起こします。
そのため、!(hoge)　は使用しない方がよいです。
```tsx:Bad
if(!hoge) {
  // Do Something
}
```
```tsx:Good
if(hoge === false) {
  // Do Something
}
```
## 返り値（null vs undefined）
undefinedは言語仕様上、プログラマーが明示的に使わなくても、自然に発生してくるものですが、nullはプログラマーが意図的に使わない限り発生しません。
なので、一般的に undefinedを使用してください。(代わりに{valid:boolean,value?:Foo}のようなオブジェクトを返すことを検討してください)
jsxでnullを返す必要がある際は、```<></>```を使用するのがいいです。
```tsx:Bad
return null;
```
```tsx:Good
return undefined;
or
return <></>
```
## UIコンポーネント用などにデータを整形しない
今後同じデータを使用するコンポーネントが増えた際にも使用できるようデータを整形しすぎない方がいいです。
```tsx:Bad
//api requestを行っているファイル
const {data} = useSWR(key,fetcher)

const toRows = (data, 他色々な条件) => {
// ifやswitchなどの条件たくさん
}

//api requestに関係のない関数
return { data, toRows}

//使う時
//各Cellの表示で条件が増えた時に辛い🔴
<UserTable rows={toRows(data)} />
```
```tsx:Good
//api requestを行っているファイル
const {data} = useSWR(key,fetcher)
//dataのみを返す✅
return {data}

//使う時
<UserTable data={data} />

//UserTable.tsx
<TableContainer>
  <Table>
    <TableHead>
      <TableRow>
        <TableCell>id</TableCell>
        <TableCell>name</TableCell>
          </TableRow>
    </TableHead>
    <TableBody>
      {data.map((row) => (
      //共通化は意識せずに愚直にかく✅
        <TableRow key={row.id}>
          <TableCell>{row.id}</TableCell>
          <TableCell{row.name}</TableCell>
        </TableRow>
      ))}
    </TableBody>
  </Table>
</TableContainer>
```
## 配列型
配列にfoos: Array<Foo>の代わりにfoos: Foo[]として配列にアノテーションをつけます。
複数形の配列は作らないようにします。
```tsx:Bad
type Count = number
type Counts = Array<Count>
type CountList = Count[]

type Props = {
  counts: Counts //countList: countList
}
```
```tsx:Good
type Count = number

type Props = {
  counts: Count[]
}
```

# おわりに
今回は、個人的に参考になったコーディングルールをまとめてみました。プロジェクト毎にルールは異なってくると思いますが、個人的に真似していこうと考えているものなので、他に参考になりそうなものがあれば教えていただけると幸いです。

# 参考
https://qiita.com/JNJDUNK/items/e040925e546a45a1d913
https://zenn.dev/kakio/articles/e7e9a753918195
https://zenn.dev/tara_is_ok/articles/05b3a6dc2ebdd7
https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null