20220108のReactに関する記事は8件です。

React レンダーの性能向上

shouldComponentUpdate 仮に、コンポーネントが一千個あるいはそれ以上ある場合、レンダーの性能が低下になりがちで、 レンダーが必要ないコンポーネントを制御するためには、「shouldComponentUpdate」を使えば済ませます。 shouldComponentUpdate(nextProps,nextState)  ・戻り値:boolean。True→Not Update, False→Update.  ・トリガー:コンポーネントの更新時(forceUpdateを除く) PureComponent PureComponentの使い方はReact.Componentと似ています。React.Componentの場所をReact.PureComponentに書き換えるだけで良いです。 両者の違いは、PureComponentは「shouldComponentUpdate」を実装しています。更新前後のProps、Stateの値を自動的に比較してくれます。ただし、その比較は浅く比較(shallow compare)だけです。 どういうことと言うと、Value Typesの比較なら、それらの値を比較します。それに対して、Reference Typesの比較なら、参照先だけを比較します、属性は比較しません。 Value Types の比較 let wallet = 0 let newWallet = wallet newWallet = 2 console.log(wallet === newWallet) //false Reference Typesの比較 const obj = { wallet: 0 } const newObj = obj newObj.wallet = 2 console.log(newObj === obj) //true //同じ参照先のため、新しいオブジェクトの属性をどう変えても、戻り値はTRUEになります。 Reference Typesの属性を比較させる方法 属性をそのまま修正するではなく、新しい属性を追加する。 const newObj = { ...state.obj, wallet: 2 } //ES6のスプレッド構文 setState({ obj: newObj }) //配列の場合 //push,unshiftを使うではなく、concat,sliceなどで新配列を返す this.setState({ obj: [...this.state.obj, { newObj }] })
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React 描写(レンダー)の性能向上方法

shouldComponentUpdate 仮に、コンポーネントが一千個あるいはそれ以上ある場合、レンダーの性能が低下になりがちで、 レンダーが必要ないコンポーネントを制御するためには、「shouldComponentUpdate」を使えば済ませます。 shouldComponentUpdate(nextProps,nextState)  ・戻り値:boolean。True→Not Update, False→Update.  ・トリガー:コンポーネントの更新時(forceUpdateを除く) PureComponent PureComponentの使い方はReact.Componentと似ています。React.Componentの場所をReact.PureComponentに書き換えるだけで良いです。 両者の違いは、PureComponentは「shouldComponentUpdate」を実装しています。更新前後のProps、Stateの値を自動的に比較してくれます。ただし、その比較は浅く比較(shallow compare)だけです。 どういうことと言うと、Value Typesの比較なら、それらの値を比較します。それに対して、Reference Typesの比較なら、参照先だけを比較します、属性は比較しません。 Value Types の比較 let wallet = 0 let newWallet = wallet newWallet = 2 console.log(wallet === newWallet) //false Reference Typesの比較 const obj = { wallet: 0 } const newObj = obj newObj.wallet = 2 console.log(newObj === obj) //true //同じ参照先のため、新しいオブジェクトの属性をどう変えても、戻り値はTRUEになります。 Reference Typesの属性を比較させる方法 属性をそのまま修正するではなく、新しい属性を追加する。 const newObj = { ...state.obj, wallet: 2 } //ES6のスプレッド構文 setState({ obj: newObj }) //配列の場合 //push,unshiftを使うではなく、concat,sliceなどで新配列を返す this.setState({ obj: [...this.state.obj, { newObj }] })
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactの環境構築 by create-react-app

はじめに これは、create-react-appの環境を構築したときのメモ。 自分のメモ用なので、見ないでくださいorz~~~。 nodeをinstall ここから自分のOSのアイコンを押してinstallする。 コマンドプロンプトを開く Windows + R cmdと入力 Ctrl + Shift + Enter Alt + y 以下はコマンドプロンプト上での作業 node, npmの確認 下記のコマンドでバージョンが表示されればO.K. node -v npm -v yarnのinstall npmは遅くて脆弱性があるらしいので、その改良版みたいなyarnを用いる方が良いらしい。 npm install -global yarn yarnのパス指定 パスが通っていれば必要なし。 以下のコマンドで得たパスを通す。環境変数を変更した後は、再起動した方が良いかも。 yarn global bin create-react-appのinstall yarn global add create-react-app create-react-appの確認 下記のコマンドでバージョンが表示されればO.K. create-react-app -v プロジェクトディレクトリに移動 cd [プロジェクトを入れるフォルダ] プロジェクトの作成 今回は my_app というプロジェクトを作成する。お好きな名前でどうぞ。因みに大文字の名前は不可だった。 create-react-app my_app プロジェクトに移動 cd my_app プロジェクトを開始 以下のコマンドを入力しブラウザが立ち上がりreactのマークが表示されれば完了! yarn start 参考文献 コマンド(2022/01/08) * https://qiita.com/rubytomato@github/items/1696530bb9fd59aa28d8 パス(2022/01/08) * https://kantaro-cgi.com/blog/nodejs/npm_and_yarn_global_install_path.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

子コンポーネントの再読み込みがかからない

目的 親コンポーネントと子コンポーネントがある。 親コンポーネントはデータアクセスがある 親コンポーネントのデータアクセス結果を子コンポーネントに伝え、それに合う表示をさせたい 環境 react@17.0.2 問題と解決方法 実現したいこと 親コンポーネントで読み込んだデータを、子コンポーネントにpropで渡し(uid等) 子コンポーネント(ProfileComp) は、propの値を元にデータを検索し表示を行いたい import React, {useState, useEffect} from "react"; // UIDを持たせるstate const [illustUid, setIllustUid] = useState(0); const Sample = (props) => { useEffect((props) => { loadData(params); },[]); // 初期表示データの読み込み処理 const loadData = (props) => { <<Firebaseからデータ取得>>.then((data) => { // ここで console.log(item.id) setIllustUid(item.id); }) } return ( <Box> <ProfileComp uid={illustUid}/> <= このコンポーネントが正しく表示されない </Box> ); } export default Sample; 問題 しかし、子コンポーネント <ProfileComp > は、親コンポーネントのデータ読み込みが完了を待たずに描画がされる 親コンポーネントが illustUid を取得完了する前に、 <ProfileComp>の描画がされてしまうため、アイコンなど子コンポーネントの内容が正しく表示されなくなっている →アイコンのところに本当はpropで受け取ったuidを元に取得した画像を表示したいが、初期表示時はuidが得られるより先に描画されてしまい、 <ProfileComp uid={null}> の状態で表示されてしまっている。useEffectで実行される loadData の読み込み処理完了後に、データが入ってから再描画したい 解決方法 state illustUid の内容に応じて子コンポーネントの描画を切り替える 親コンポーネントの読み込みが完了し、illustUid に値がセットされたら、子コンポーネントを表示する次のような式にする {illustUid&& <ProfileComp uid={illustUid}/>} illustUidにデータが入ると<ProfileComp uid={illustUid}/> の再描画が走り、子コンポーネントが正しいデータで表示される import React, {useState, useEffect} from "react"; // UIDを持たせるstate const [illustUid, setIllustUid] = useState(0); const Sample = (props) => { useEffect((props) => { loadData(params); },[]); // 初期表示データの読み込み処理 const loadData = (props) => { <<Firebaseからデータ取得>>.then((data) => { // ここで console.log(item.id) setIllustUid(item.id); }) } return ( <Box> {illustUid&& <ProfileComp uid={illustUid}/>} <= 修正箇所 </Box> ); } export default Sample;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React setState() データ同期&非同期の書き方

データ非同期更新 setState()のデータ更新は非同期です。 同じスコープ内にsetState()を複数回呼び出されたも、render()は一回しか呼ばされないです。 //非同期更新 handleClick = () => { this.setState({ count: this.state.count + 1 }) console.log('first', this.state.count) //1 this.setState({ count: this.state.count + 1 }) console.log('second', this.state.count) //1 } データを同期更新させる方法 setState((state,props)⇒{}) を使用することです。  ・state: 最新のstate  ・props: 最新のprops handleClick = () => { this.setState((state, props) => { return { count: state.count+1 } }) this.setState((state, props) => { console.log('second',this.state) //2 return { count: state.count+1 } }) console.log(this.state.count) //1 これを先にプリントする } setState()の第二引数 setState(updater[,callback]) UIレンダリング後に、setStateの第二引数callbackを直ちに実行します。 handleClick = () => { this.setState( //第一引数 updater (state, props) => { return { count: state.count+1 } }, //第二引数 callback () => { console.log(document.title) } ) } コンポーネント更新の仕組み setState() の役割は大きく二つに分けられます。 1. stateの更新 2. コンポーネントの更新 コンポーネントを更新する際に、子要素のコンポーネントしか更新しません。 兄弟や親のコンポーネントは更新しません。 黄色部分は更新するところ 注意すべきところ レンダリング必要あるのデータだけ、stateに入れますが、 レンダリング必要ないデータはthisに入れます。 stateのデータが多ければ多いほど、renderの性能が低下してしまいます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

react hooks useState 実用的なオブジェクト配列管理

カスタムHooks useState でオブジェクト配列を扱う場合のテンプレート的なものです。 typescriptも便利な機能を十分に活用し簡潔で機能的な記述を行います。 オブジェクト配列を扱う場合には、1つのアイテムを追加したり、削除の必要が多いかと思います。 そのような機能を簡潔に実装し、汎用的に使える想定のカスタムステートです。 useItems.ts import { useState, useCallback } from 'react' type ItemBase = { id: string } type FilterOptions = { not: boolean } export const useCustomState = <T extends ItemBase>(defaultItems: T[] = []) => { const [items, setItems] = useState<T[]>(defaultItems) // Filter read const filter = useCallback( (key: keyof T, value: any, options?: FilterOptions) => { if (options?.not) { return items.filter((item) => item[key] !== value) } return items.filter((item) => item[key] === value) }, [items], ) // Create const add = (item: T) => { setItems((prev) => [...prev, item]) } // Update const update = (id: string, updateParams: Omit<Partial<T>, 'id'>) => { setItems((prev) => { const anotherItems = prev.filter((item) => item.id !== id) const currentItem = prev.find((item) => item.id === id) if (!currentItem) return prev return [ ...anotherItems, { ...currentItem, ...updateParams, }, ] }) } // Remove const remove = (id: string) => { setItems((prev) => prev.filter((item) => item.id !== id)) } return { items, filter, add, update, remove } } Stateオブジェクトの型を定義できるようにする type ItemBase = { id: string } export const useCustomState = <T extends ItemBase>(defaultItems: T[] = []) => {} typescript のジェネリックを使い、管理するオブジェクトの入力補完やコンパイルエラーが発生するようにします。 プロパティ "id" は必須にする T extends ItemBase とすることで、利用するオブジェクトにはIDを必須にします。これにより各メソッドの処理を保証します。 簡単なフィルターを実装する type FilterOptions = { not?: boolean } // Filter read const filter = useCallback( (key: keyof T, value: any, options?: FilterOptions) => { if (options?.not) { return items.filter((item) => item[key] !== value) } return items.filter((item) => item[key] === value) }, [items], ) 簡単なフィルタリングを用意。 keyof T とすることで、指定キーがオブジェクト内に存在することを保証しつつ、入力補完を効かせます。 アップデートではidの上書きを防ぐ // Update const update = (id: string, updateParams: Omit<Partial<T>, 'id'>) => { setItems((prev) => { const anotherItems = prev.filter((item) => item.id !== id) const currentItem = prev.find((item) => item.id === id) if (!currentItem) return prev return [ ...anotherItems, { ...currentItem, ...updateParams, }, ] }) } 1つのアイテムのみを更新する場合は、スプレッド演算子によるマージを行います。 その最、 Omit<Partial<T>, 'id'>によって更新データには id を含めてはいけないようにすることで、idの上書きを防ぐことができます。 Omit: 指定のプロパティを取り除く(今回は id を取り除く) Partial: プロパティを必須から外す これで、typescriptの機能を有効に使い、スッキリとオブジェクト配列管理のuseStateを書くことができました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React lifecycle ライフサイクル

React ライフサイクルとは reactのライフサイクルはコンポーネントの誕生から消滅までに発生する一連のイベントとのことです。 reactのライフサイクルは三つの時期に分けられます。  ・Mounting—>コンポーネントの誕生  ・Update—>コンポーネントの更新  ・Unmount—>コンポーネントの停止 The diagram below is from the official React documentation マウント時 マウント時の実行順番 Hook トリガー 役割 constructor コンポーネント作成時 1. state初期化2.イベントハンドラをインスタンスにバインドする render レンダー時 UIレンダリング(注1:setState()を使ってはいけない。renderの用途はレンダリングだけのため。) componentDidMount コンポーネントがマウント後 1.ネットワークリクエストを送信2.DOMに対する操作 ※注1: render内にsetState() を使用すると、無限ループになってしまう。 更新時 Hook トリガー 役割 render レンダー時 UIレンダリング(マウント時のrender) componentDidUpdate 1. setState()2. forceUpdate()3. New Props(注2:上記のいずれもトリガーになる) 1.ネットワークリクエストを送信2.DOMに対する操作(注3:setState()の設定はif文に入れる必要有) ※注3:無限ループになるため。 class App extends React.Component { constructor(props) { super(props) this.state { count: 0 } } handleClick = () => { this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <Counter count={this.state.count} /> <button onClick={this.handleClick}> Click </button> </div> ) } } class Counter extends React.Component { render() { return <h1 id="content"> Click count: {this.props.count}</h1> } //下記は悪い例:無限ループになる /* componentDidUpdate() { this.setState({}) } */ //正しい例:if文に入れる componentDidUpdate(prevProps) { if (prevProps.count !== this.props.count) { this.setState({}) } } } アンマウント時 Hook トリガー 役割 componentWillUnMount コンポーネントがアンマウントされて破棄される直前 コンポーネントのアンマウント componentDidMountで作成したコンポーネントを廃棄しようと思う時、componentWillUnmoutを呼び出す。 class Counter extends React.Component { //set Timer componentDidMount() { this.timerId = setInterval(() => { console.log('timer') }, 500) } render() { return <h1 id="content"> Click count: {this.props.count}</h1> } //Timer Unmount componentWillUnmount() { clearInterval(this.timerId) } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AntDesignのAvatarを自作してみた

1. 自作した理由 通っていたスクールで依存度が高いAntDesignからの脱却を目指していたため、その流れで自分もチャレンジしてみようと感じた。 2. 開発環境 react v16.12.0 styled-components v5.3.3 typescript v4.1.4 3. 実装した機能 まずは、AntDesignのAvatarに搭載されている機能を紹介します。 正直使わない機能が多かったため、自作した際には最低限使いそうなsrc size border shapeのみを実装しました。 4. 実際のコード import React from 'react'; import styled, { css } from 'styled-components'; type Props = { src?: string | null; size?: number | 'large' | 'small' | 'default'; border?: boolean; shape?: 'circle' | 'square'; }; const AvatarStyle = styled.div<Props>` ${props => { if (!props.size) { return css` width: 40px; height: 40px; border-radius: 50%; `; } else { if (props.size === 'default') { return css` width: 40px; height: 40px; border-radius: 50%; `; } else if (props.size === 'small') { return css` width: 32px; height: 32px; border-radius: 50%; `; } else if (props.size === 'large') { return css` width: 64px; height: 64px; border-radius: 50%; `; } else { return css` width: ${props.size}px; height: ${props.size}px; border-radius: 50%; `; } } }} border: ${props => props.border && '1px solid blue'}; background-color: gray; border-radius: ${props => props.shape === 'square' && '0%'}; background-size: cover; background-repeat: no-repeat; background-position: center; background-image: url(${props => props.src}); `; const AtomAvatar: React.FC<Props> = ({ ...props }) => { return <AvatarStyle {...props} />; }; export default AtomAvatar; 5. 苦戦した点 sizeを設定する際にdefault、small、largeと数字指定の両立に苦戦した。 そこでdefaultなどの文字列が渡ってきた際には指定のピクセル数を指定し、それ以外の場合は入力した数字を渡し、Ant Designを忠実に再現した。 6. 未実装だが必要だと感じる機能 画像をユーザー自身で変更できる機能 現状は開発者側でsrcを指定すれば任意の画像は設定可能だが、ユーザー側では変えることはできない。 この機能に関してアドバイスなどありましたら、コメントとかで教えていただきたいです 7. 後書き アウトプットの目的で初めて書いたが、改めて書いた意図を理解することができた。 正直スクールの講師の方にアドバイスをいただいた部分が多いため、他のAnt Designも自作してみようかと考えている。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む