ユーザ状態の関数更新によるユーザコールバック状態依存性の解消
useStateを更新する従来の方法
import React, { useState, useCallback } from 'react';
const myCompo = () => {
const [todos, setTodos]
= useState([{id:1, text:'병원가기', checked:false}]);
const onAdd = useCallback((e)=>{
e.preventDafault();
setTodos(todos.concat({id:2, text:'애플스토어가기', checked:false}));
}, [todos])
const onRemove = useCallback((e, id)=> {
e.preventDefault();
let tempData = todos.filter(todo=>todo.id!==id);
setTodos(tempData);
}, [todos])
return(
// 생략..
)
}
アクティブハンドルはonAdd
、onRemove
です.onAdd
において、concat
関数が返す新しい配列は、setTodos()
に依然として使用される.onRemove
は、filter
関数によって返される新しい配列を一時変数tempData
に格納し、tempData
はsetTodos()
に使用される.両方のイベントハンドルはtodosに依存します.既存のtodosをクエリーして新しい配列を作成するためです.
したがって、
useCallback
は第2の因子として列挙されるべきである.なぜなら、todos
が更新または変更された場合、イベントハンドラは再宣言する必要があるからです.useState関数式更新
import React, { useState, useCallback } from 'react';
const myCompo = () => {
const [todos, setTodos]
= useState([{id:1, text:'병원가기', checked:false}]);
const onAdd = useCallback((e)=>{
e.preventDafault();
setTodos(todos=>
todos.concat({id:2, text:'애플스토어가기', checked:false}));
}, [])
const onRemove = useCallback((e, id)=> {
e.preventDefault();
setTodos(todos=>todos.filter(todo=>todo.id!==id));
}, [])
return(
// 생략..
)
}
todos
を関数型更新に変更します.useState
の更新方式を関数型に変更し、以下に示すようにArrow Functionの形式に変更します.setTodos
in setTodos
setTodos(todos=>todos.concat({id:2, text:'애플스토어가기', checked:false}));
onAdd()
in setTodos
setTodos(todos=>todos.filter(todo=>todo.id!==id));
これにより、onRemove()
でstate値の依存性を解消し、2番目のパラメータを空の配列に指定することができる.なぜ依存性がないのでしょうか。
関数型更新方式の変更に伴い、関数のパラメータは
useCallback()
を超えた.既存の変数をパラメータに変換すると、依存性が失われます.
let num = 10;
function addfunc(value) {
value = value + 10;
}
addfunc(num);
console.log(num) // 10
上記コードに示すように、todos
以外で宣言された기존 변수 !== 매개변수
という変数を関数のパラメータとして渡し、10を加算するロジックを行うと、実際の関数以外のaddfunc()
という変数が出力され、10が出力される.関数のnum
とnum
は異なります.したがって、
num
を関数的に更新して使用すると、함수 밖의 num
からuseState
の値を直接問い合わせるのではなく、間接的に問い合わせるので依存性がなくなります.パフォーマンスの向上
USStateを関数として更新しても、パフォーマンスは良くなりません.ただし、以下のコードを参照してください.
// tempCompo.jsx
import React, { useState, useCallback } from 'react';
import listItem from './listItem';
const tempCompo = () => {
const [todos, setTodos] = useState(
{
id: 1,
text : '학교가기',
checked: false
},
{
id: 2,
text: '애플스토어가기',
checked: false
}
)
// 함수형 업데이트 방식 X
const onToggle = useCallback(()=> {
setTodos(todos =>
todos.map(todo=>
todo.id ===id ? {...todo, checked: !todo.checked} : todo))
}, [todos])
return(
{todos.map(
(<listItem key={todo.id} checked={todo.checked}
text={todo.text} onToggle={onToggle}/>))}
)
}
//listItem.jsx
import React from 'react';
const listItem = ({checked, text, onToggle}) => {
return(
<div> {text} </div>
<button onClick={onToggle}>버튼</button>
)
}
export default React.memo(listItem);
以上のように、usStateは、関数更新ではなく従来の方法で実現され、useCallback
〜state
を用いて素子最適化が行われた.listItem.jsx
の構成部品のみを表示します.React.memo()
の構成部品は、ボタンを押してlistItem
の"학교가기"
をtrueに変更しても再レンダリングされません.しかしchecked
の観点から"애플스토어가기"
の値state
が変化したため、再生state
には資源浪費があった.USState関数式の更新によって実現される場合、素子の最適化は予想通りに行うことができる.
Reference
この問題について(ユーザ状態の関数更新によるユーザコールバック状態依存性の解消), 我々は、より多くの情報をここで見つけました https://velog.io/@apro_xo/React.js-useState의-함수형-업데이트를-통한-useCallback-상태-의존성-없애기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol