memo、useCallback、useMemoとuseEffectは違います.
7179 ワード
問題の導入
サブコンポーネントのは、着信したname属性だけに依存しているが、親コンポーネントname属性とtext属性の変化は、いずれもPartent関数の再実行をもたらし、したがって、着信したサブアセンブリpropsが変化していなくても、サブアセンブリが任意のprops属性に依存していないため、サブアセンブリが新たにレンダリングされることになる.
memoパッケージを使用する場合は、プロpsが変更されたサブコンポーネントだけが再レンダリングされます.memoを使うと、一定の性能が向上します.
useCallbackはキャッシュ関数として使用され、依存項が変更された場合にのみ、関数が新しい関数に戻ります.親コンポーネントの関数がpropsとしてサブアセンブリに伝達された場合、親コンポーネントのデータが変更され、関数が再実行される限り、プロpsの関数として新しいインスタンスが生成され、サブアセンブリのリフレッシュにuseCallbackを使用して関数をキャッシュすることができます.memoを組み合わせて使う必要があります.
useMemoの使用シーンは以下の例を見てください.getTotalは非常に高価な動作であると仮定しますが、この関数の結果はcountとpriceにのみ依存します.しかし、色の変化によって、DOM再レンダリングもその関数の実行につながります.useMemoはこの関数をキャッシュするための実行結果です.依存項が変更された場合のみ再計算されます.
以上のuseMemoの例もuseeffectを使って実現できます.useffectを使って書き換えた結果です.
サブコンポーネントのは、着信したname属性だけに依存しているが、親コンポーネントname属性とtext属性の変化は、いずれもPartent関数の再実行をもたらし、したがって、着信したサブアセンブリpropsが変化していなくても、サブアセンブリが任意のprops属性に依存していないため、サブアセンブリが新たにレンダリングされることになる.
const Child = ((props: any) => {
console.log(" ...");
return (
text:{props.name}
{new Date().getTime()}
)
})
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("")
const handleClick = () => {
setCount(count + 1);
}
const handleInputChange = (e) => {
setText(e.target.value)
}
return (
count:{count}
)
}
モモmemoパッケージを使用する場合は、プロpsが変更されたサブコンポーネントだけが再レンダリングされます.memoを使うと、一定の性能が向上します.
const Child = memo((props: any) => {
console.log(" ..."); // props , name ,
return (
text:{props.name}
{new Date().getTime()}
)
})
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("")
const handleClick = () => {
setCount(count + 1);
}
const handleInputChange = (e) => {
setText(e.target.value)
}
return (
count:{count}
)
}
しかし、導入されたプロpsが関数を含む場合、親コンポーネントは毎回新たな関数を作成するので、伝達関数サブコンポーネントはまた、関数の内容が同じであっても再レンダリングされる.どうやってこの問題を解決しますか?私たちは関数をキャッシュしたいので、アメリカのCallbackを導入します.const Child = memo((props: any) => {
console.log(" ..."); // count , ,handleInputChange ,
return (
text:{props.name}
{new Date().getTime()}
)
})
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("")
const handleClick = () => {
setCount(count + 1);
}
const handleInputChange = (e) => {
setText(e.target.value)
}
return (
count:{count}
)
}
useCallbackuseCallbackはキャッシュ関数として使用され、依存項が変更された場合にのみ、関数が新しい関数に戻ります.親コンポーネントの関数がpropsとしてサブアセンブリに伝達された場合、親コンポーネントのデータが変更され、関数が再実行される限り、プロpsの関数として新しいインスタンスが生成され、サブアセンブリのリフレッシュにuseCallbackを使用して関数をキャッシュすることができます.memoを組み合わせて使う必要があります.
const Child = memo((props: any) => {
console.log(" ...");
return (
text:{props.name}
{new Date().getTime()}
)
})
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("")
const handleClick = () => {
setCount(count + 1);
}
const handleInputChange =useCallback((e) => {
setText(e.target.value )
},[])
return (
count:{count}
)
}
useCallbackの二つ目のパラメータ依存項はどのような場合に使いますか?次の例を見てください.// handleInputChange
const handleInputChange =useCallback((e) => {
setText(e.target.value + count)
},[])
上記の例でcountが変わるとどうなりますか?countは変更されましたが、handleInput Changeは任意の項目に依存しませんので、handleInput Changeは初期化時に関数を呼び出すだけでキャッシュされます.テキストが変更された時やcountが変更された時に関数内部のcountは常に0です.したがって、countを依存項に追加し、countが変化したら新たな関数を生成し、関数内部のcount値を変更する必要があります.const handleInputChange =useCallback((e) => {
setText(e.target.value + count)
},[count])
use MemouseMemoの使用シーンは以下の例を見てください.getTotalは非常に高価な動作であると仮定しますが、この関数の結果はcountとpriceにのみ依存します.しかし、色の変化によって、DOM再レンダリングもその関数の実行につながります.useMemoはこの関数をキャッシュするための実行結果です.依存項が変更された場合のみ再計算されます.
const Parent = () => {
const [count, setCount] = useState(0);
const [color,setColor] = useState("");
const [price,setPrice] = useState(10);
const handleClick = () => {
setCount(count + 1);
}
const getTotal = ()=>{
console.log("getTotal exec ...") // count price, color
return count * price
}
return (
: setColor(e.target.value)}/>
: setPrice(Number(e.target.value))}/>
:{count}
:{getTotal()}
)
}
修正後は以下の通りです.useMemoキャッシュのは関数実行の結果です.const Parent = () => {
console.log("parent exec...")
const [count, setCount] = useState(0);
const [color,setColor] = useState("");
const [price,setPrice] = useState(10);
const handleClick = () => {
setCount(count + 1);
}
const getTotal = useMemo(()=>{
console.log("getTotal exec ...")
return count * price
},[count, price])
return (
: setColor(e.target.value)}/>
: setPrice(Number(e.target.value))}/>
:{count}
:{getTotal}
)
}
useMemoとuseEffectは違います.以上のuseMemoの例もuseeffectを使って実現できます.useffectを使って書き換えた結果です.
const Parent = () => {
console.log("parent exec...")
const [count, setCount] = useState(0);
const [color,setColor] = useState("");
const [price,setPrice] = useState(10);
const [total,setTotal] = useState(0)
useEffect(()=>{
setTotal(price * count)
},[price,count])
const handleClick = () => {
setCount(count + 1);
}
return (
: setColor(e.target.value)}/>
: setPrice(Number(e.target.value))}/>
:{count}
:{total}
)
}
なお、useffectはprice、countのいずれかの変化後にトリガされ、totalが変更されると、関数の再実行がトリガされ、コンポーネントが再レンダリングされるので、制御セットでは「parent exec...」が2回印刷され、最初の例では「parent exec...」が表示されます.一回だけ印刷されたので、以下のようにまとめられています.useffectはDOM変更後にトリガされ、useMemoはDOM再レンダリングの前にuseEffect設定値をトリガすると再レンダリングされますが、useMemoは再レンダリングされません.