20200220のReactに関する記事は3件です。

reactのmemoが使いこなせない

reactのmemoが使いこなせない...

【助けていただいたサイト一覧】
- 公式様
- react.memoの解説がとても分かり易かったです

出発の問題

前提: react.memoの仕様の把握

react.memoを使ってパフォーマンスアップするぞーと意気込んでいました。
作業内容は、あるデータをループで回してリスト化する。あるあるです。

スクリーンショット 2020-02-20 15.52.41.png

このデータはしょっちゅう変更されますが、

// 前回データ
[0:{title: 'わに'},
 1:{title: 'とり'},
 2:{title: 'いるか'}
]

// 変更後データ
[0:{title: 'わに'},
 1:{title: 'かば'},
 2:{title: 'やぎ'}
]

であった場合、0個目のリストのpropsは変わらないので、再レンダリングするのはエコではありません。

コードで示すと以下のようになります。

parent.js
Parent = () => {
  const [stateTest, setTest] = useState({
    array: [
      {title: 'わに'},
      {title: 'とり'},
      {title: 'いるか'}
    ]
  })

  const propsChanger = () => {
    setTest({
      array: [
        {title: 'わに'},
        {title: 'かば'},
        {title: 'やぎ'}
      ]
    })
  }

  let ListDom = []
  stateTest.array.forEach((item) => {
    ListDom.push(
      <List objData={item} key={`list${i}`}/>
    )

  return (
    <div>
      {ListDom}
      <div onClick={propsChanger}>props更新!</div>
    </div>
  )
}
List.js
export default function List ({objData}) {
  console.log(`${objData.title}はレンダリング`)
  return(
    <p>{objData.title}</p>
  )
}

再レンダリングさせない...react.memoの出番だ!と思ったわけです。

import React, { memo } from 'react'

const List = memo(({objData}) => {
  console.log(`${objData.title}はレンダリング`)
  return(
    <p>{objData.title}</p>
  )
})

export default List

メモをかませたので、shallowで比較されるはず、、!
と思って更新ボタンを押すと、

スクリーンショット 2020-02-20 17.24.31.png

わに、しっかり再レンダリングされていました...

なぜ?

オブジェクトの比較はインスタンスが違うと中身が同じでも同等と見なされないから。
memoを使いこなすのは難しそうです。

解決方法!

その1 オブジェクト・配列は渡さない。

Parent
stateTest.array.forEach((item, i) => {
  ListDom.push(
    <List title={item.title} key={`list${i}`}/>
  )
})
List
const List = memo(({title}) => {
  console.log(`${title}はレンダリング`)
  return(
    <p>{title}</p>
  )
})
export default List

propsを文字列で渡すようにしました。これであれば わにのリストは再レンダリングされませんでした。
でも、渡す情報が多い場合は、propsをたくさん渡さなければなりません。

その2 第二引数を使う

deepな比較はshallowよりコストが高いので注意です!

どうして失敗したのか

shallowでの比較の意味を取り違えていたせいです。
propsからみて一階層下の比較を行う、ということだったんですね。
渡したobject(props.object)から一回層下の比較を行う、という意味と取り違えていました。

追記

https://qiita.com/takujiro_0529/items/c7eb194efefbabdb2575
こんな記事を見つけました!
まだ未検証ですが、useMemoだったら私の想定していたshallow compareになるようです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Auth0をSPAアプリケーションでブラウザをリロードすると認証情報が消えてしまうときの対処

react-auth0-spa.jsなどを使ってReactでAuth0を認証に使ったSPAアプリを作っているときに、認証したあとブラウザをリロードするとログアウト状態にされてしまうことがある。その時のAuth0のログには、

Failed Silent Auth - Login required

などと表示される。Auth0の設定は合っているが、この状況になるときはユニバーサルログインの種類がClassicになっている可能性がある。

下記手順でユニバーサルログインをNewに変更すると解消する。

Universal Loginリンク

Screenshot_2020_02_20_17_41.png

Newを選択

Screenshot_2020_02_20_17_42.png

保存

Screenshot_2020_02_20_17_43.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】this.setStateの即時反映

困ったこと

Formの入力欄をリアルタイムでバリデーションしたいけど,this.setStateが即時に反映されない.

.js
class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      foo: 1
    };
  }

  foo_setTwo = () => {
    this.state({ foo: 2 });
    console.log(foo); // foo : 1
  }
}

解決法

コールバックで呼び出すか,reactのライフサイクルでcomponentDidUpdateメソッドを使うか.

.js
  foo_setTwo = () => {
    this.state({ foo: 2 }, () => {
      console.log(foo); // foo : 2
    });
  }

  componentDidUpdate(prevProps, prevState, snapshot){
    console.log(this.state.foo); // foo : 2
  }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む