えー！めっちゃ便利じゃん！と思ったlodashの関数を紹介する

## はじめに
JavaScriptのユーティリティライブラリの一つにLodashというものがあります。

業務で配列を扱うために使っていて、便利なので重宝しています。
しかし、配列操作以外にも便利なものが結構あることを知ったので、それらを紹介します。

## debounce
### 概要
一度発火すると、一定時間は再発火されない関数を定義することができます。
フォームのユーザー入力によってAPIを呼び出す処理の場合に有効です。

### 基本形
`_.debounce(func,wait,option)`
#### func
実行したい処理を指定します。

#### wait
待機する時間を指定します。単位はミリ秒です。

#### option
オブションをオブジェクトの形式で指定します。
設定できるのは以下の3つのプロパティです。
`{leading:boolean, maxWait:number, trailing:boolean}`
今回は扱わないので、詳細は割愛します。

### 使用例

以下のような、入力結果に合わせてリアルタイムで検索するような画面があるとします。
<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/f8f4c562-7f44-176a-c4e8-c55475369af2.png'>

入力フォームの`onChange`イベントに検索処理を設定するかと思いますが、`onChange`イベントは1文字入力するたびに発火するので、そのままだと少し使いにくいです。

そんなときに`debounce`を使います。

```react
import { useState } from "react";
import _ from "lodash";
const LodashPractice = () => {
  const [results, setResults] = useState<string[]>([]);

  const handleSearch = _.debounce((term: string) => {
    // 実際のAPI呼び出しをシミュレート
    setResults([`Result for ${term}`]);
  }, 300);

  return (
    <div>
      <input
        type="text"
        onChange={(e) => handleSearch(e.target.value)}
        placeholder="検索..."
      />
      <ul>
        {results.map((result, index) => (
          <li key={index}>{result}</li>
        ))}
      </ul>
    </div>
  );
};

export default LodashPractice;
```

debounceに実行したい処理を設定し、待機時間に300ミリ秒を指定したので、その間は入力値の変更があっても、処理は実行されません。

1文字ごとに検索処理が走るとちょっと使い勝手がわるいですが、これは若干待機の時間があるので、より使いやすいフォームになっています。

:::note info
これとよく似た処理で`throttle`という関数があります。
今回は割愛しますが、こちらも便利なのでおすすめです。
:::

## get
### 概要
ネストされたオブジェクトの値を取得するために使います。
値が取得できなかった場合にデフォルト値を設定することができるので、不要な条件分岐を減らせます。

### 基本形
`_.get(object,path,defaultValue)`

#### object
取得元となるオブジェクトです。

#### path
プロパティを取得するためのパスです。
`{ users:{ name:'taro', age:20 } }`
このようなオブジェクトがあった場合、パスは
`users.name`
のような形になります。

配列を含んでいても取得可能です。
`{ users:[ { name:'taro', age:20 }, { name:'jiro', age:15 } ] }`
このようなオブジェクトがあった場合、パスは
`users[0].name`
のような形になります。

#### defaultValue
pathで指定したプロパティの取得結果が`undefined`の場合に設定される値です。

### 使用例
ユーザー情報オブジェクトの中で、任意の設定プロパティがあるとします。
今回は、`phone`が未設定のユーザー情報を画面に設定します。

```react
import _ from "lodash";

interface User {
  name: string;
  contacts?: {
    email?: string;
    phone?: string;
  };
}

const user: User = {
  name: "Taro",
  contacts: {
    email: "taro@testmail",
  },
};

const GetPractice = () => {
  const email = _.get(user, "contacts.email", "なし");
  const phone = _.get(user, "contacts.phone", "なし");

  return (
    <div>
      <h2>{user.name}の連絡先</h2>
      <p>Email: {email}</p>
      <p>電話: {phone}</p>
    </div>
  );
};
export default GetPractice;
```

`get`でデフォルト値を設定しているので、未設定があっても結果はエラーにならず、以下のように表示されます。

<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/93de4bf7-20be-2b95-4f22-7c9ab68da07c.png'>

## cloneDeep
### 概要
ネストされたオブジェクトの完全なコピーを作成することができます。
通常、ネストされたオブジェクトを複製するのは結構な手間がかかりますが、これを使うことで簡単にディープコピーが生成できます。

### 基本形
`cloneDeep(object)`

#### object
コピー対象のオブジェクトです。

### 使用例
以下のように、タスクをクリックすることで完了 / 未完了の切り替えをする簡易タスク管理アプリがあるとします。

<img width='70%' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251137/c647fad6-4fd8-df75-549d-536de977e034.png'>

タスクオブジェクトの配列を`state`で管理することになりますが、`state`の更新のためには、新しい配列を生成する必要があります。

```react
import { useState } from "react";
import _ from "lodash";

interface Task {
  id: number;
  title: string;
  completed: boolean;
}

const CloneDeepPractice = () => {
  const [tasks, setTasks] = useState<Task[]>([
    { id: 1, title: "タスク1", completed: false },
    { id: 2, title: "タスク2", completed: false },
    { id: 3, title: "タスク3", completed: false },
  ]);

  const toggleTask = (id: number) => {
    const newTasks = _.cloneDeep(tasks);
    const task = newTasks.find((t) => t.id === id);
    if (task) {
      task.completed = !task.completed;
      setTasks(newTasks);
    }
  };

  return (
    <ul>
      {tasks.map((task) => (
        <li key={task.id} onClick={() => toggleTask(task.id)}>
          {task.title} - {task.completed ? "完了" : "未完了"}
        </li>
      ))}
    </ul>
  );
};

export default CloneDeepPractice;
```
`cloneDeep`を使うことで、余計な処理を書くことなく完全なコピーを作成できるため、簡潔に処理を実装することができました。


## まとめ
lodashの関数で、配列操作以外で便利だなと思ったものを紹介しました。
ほかにもまだまだあるので、次回もlodashを扱います。