React memoでオブジェクトをpropsで渡したときの動き

# memoにオブジェクトを渡す

基本的にmemoはshallow比較なのでオブジェクトは比較されないとなっていたので検証する。

```jsx
import React, { useState, memo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [cnt, setCnt] = useState(0);
  const arr = [];
  return (
    <div className="App">
      {cnt}
      <button onClick={() => setCnt(cnt + 1)}>button</button>
      <Test arr={[]} />
    </div>
  );
}

const Test = memo(({ arr }) => {
  console.log("test", { arr });
  return <div>test</div>;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

```

![Nov-09-2019 18-15-16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/4299559d-5ae1-3d58-17cb-6c43a78d6bcc.gif)

確かにレンダリングされる。

## useMemoつかったら？

やってみる。

```js
import React, { useState, memo, useMemo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [cnt, setCnt] = useState(0);
  const arr = useMemo(() => [], []);
  return (
    <div className="App">
      {cnt}
      <button onClick={() => setCnt(cnt + 1)}>button</button>
      <Test arr={arr} />
    </div>
  );
}

const Test = memo(({ arr }) => {
  console.log("test", { arr });
  return <div>test</div>;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

![Nov-09-2019 18-20-34.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/ff4d6202-dc34-af46-8358-dc07c87a2d2c.gif)

お！！？？
レンダリングされない！
なるほど、、

# useMemoの更新

少しわかりにくいが、３の倍数のときのみuseMemoで再キャッシュするようにする。
理想は、その時だけmemoしたコンポーネントだけ更新されること。

```js
import React, { useState, memo, useMemo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [cnt, setCnt] = useState(1);
  const [cnt3, setCnt3] = useState(0);
  if (cnt % 3 === 0 && cnt !== cnt3) setCnt3(cnt);
  const arr = useMemo(() => [], [cnt3]);
  return (
    <div className="App">
      {cnt}
      <button onClick={() => setCnt(cnt + 1)}>button</button>
      <Test arr={arr} />
    </div>
  );
}

const Test = memo(({ arr }) => {
  console.log("test", { arr });
  return <div>test</div>;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

![Nov-09-2019 18-32-41.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/fee1d134-ade1-a10a-6b2b-9a747ccedc16.gif)

おー！
想定どおり！！

# Objectもやってみる

## useMemoを使わない

```js
import React, { useState, memo, useMemo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [cnt, setCnt] = useState(1);
  const obj = {};
  return (
    <div className="App">
      {cnt}
      <button onClick={() => setCnt(cnt + 1)}>button</button>
      <Test arr={obj} />
    </div>
  );
}

const Test = memo(({ obj }) => {
  console.log("test", { obj });
  return <div>test</div>;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

![Nov-09-2019 18-36-13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/42394d42-38fe-dc6f-92ff-0df62a0454d9.gif)

レンダリングされる。

## useMemoを使う

```js
import React, { useState, memo, useMemo } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [cnt, setCnt] = useState(1);
  const obj = useMemo(() => ({ 'ttt': 1 }), []);
  return (
    <div className="App">
      {cnt}
      <button onClick={() => setCnt(cnt + 1)}>button</button>
      <Test obj={obj} />
    </div>
  );
}

const Test = memo(({ obj }) => {
  console.log("test", obj.ttt);
  return <div>test</div>;
});

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

![Nov-09-2019 18-40-52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/b56b0d54-4df1-6c34-edec-796d786cf989.gif)


# まとめ
memoはオブジェクトを比較してるのではなくて、参照を見ていることが確定したのと、
useMemoを使えば、オブジェクトもmemoの対象にできることがわかった！
これから使っていこう！！