Laut den Dokumenten:
componentDidUpdate()
wird sofort nach der Aktualisierung aufgerufen. Diese Methode wird beim ersten Rendern nicht aufgerufen.
Wir können den neuen useEffect()
Hook zum Simulieren verwenden componentDidUpdate()
, aber es scheint, useEffect()
als würde er nach jedem Rendern ausgeführt, sogar beim ersten Mal. Wie kann ich erreichen, dass es beim ersten Rendern nicht ausgeführt wird?
Wie Sie im folgenden Beispiel sehen können, componentDidUpdateFunction
wird es beim ersten Rendern componentDidUpdateClass
gedruckt , wurde jedoch beim ersten Rendern nicht gedruckt.
function ComponentDidUpdateFunction() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
console.log("componentDidUpdateFunction");
});
return (
<div>
<p>componentDidUpdateFunction: {count} times</p>
<button
onClick={() => {
setCount(count + 1);
}}
>
Click Me
</button>
</div>
);
}
class ComponentDidUpdateClass extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
}
componentDidUpdate() {
console.log("componentDidUpdateClass");
}
render() {
return (
<div>
<p>componentDidUpdateClass: {this.state.count} times</p>
<button
onClick={() => {
this.setState({ count: this.state.count + 1 });
}}
>
Click Me
</button>
</div>
);
}
}
ReactDOM.render(
<div>
<ComponentDidUpdateFunction />
<ComponentDidUpdateClass />
</div>,
document.querySelector("#app")
);
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
javascript
reactjs
react-hooks
Yangshun Tay
quelle
quelle
count
?Antworten:
Wir können den
useRef
Hook verwenden, um einen beliebigen veränderlichen Wert zu speichern , damit wir verfolgen können, ob dieuseEffect
Funktion zum ersten Mal ausgeführt wird.Wenn der Effekt in derselben Phase ausgeführt werden
componentDidUpdate
soll, können wir ihnuseLayoutEffect
stattdessen verwenden.Beispiel
const { useState, useRef, useLayoutEffect } = React; function ComponentDidUpdateFunction() { const [count, setCount] = useState(0); const firstUpdate = useRef(true); useLayoutEffect(() => { if (firstUpdate.current) { firstUpdate.current = false; return; } console.log("componentDidUpdateFunction"); }); return ( <div> <p>componentDidUpdateFunction: {count} times</p> <button onClick={() => { setCount(count + 1); }} > Click Me </button> </div> ); } ReactDOM.render( <ComponentDidUpdateFunction />, document.getElementById("app") );
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script> <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script> <div id="app"></div>
quelle
useRef
mituseState
, aber die Setter mit ausgelöst einem erneuten machen, das ist nicht der Fall , wenn auf der ZuordnungfirstUpdate.current
so dass ich denke , das ist die einzige nette Weise ist :)componentDidUpdate
mit Haken nachahmt , deshalb habe ich es verwendet.Sie können es wie folgt in benutzerdefinierte Haken verwandeln :
import React, { useEffect, useRef } from 'react'; const useDidMountEffect = (func, deps) => { const didMount = useRef(false); useEffect(() => { if (didMount.current) func(); else didMount.current = true; }, deps); } export default useDidMountEffect;
Anwendungsbeispiel:
import React, { useState, useEffect } from 'react'; import useDidMountEffect from '../path/to/useDidMountEffect'; const MyComponent = (props) => { const [state, setState] = useState({ key: false }); useEffect(() => { // you know what is this, don't you? }, []); useDidMountEffect(() => { // react please run me if 'key' changes, but not on initial render }, [state.key]); return ( <div> ... </div> ); } // ...
quelle
Ich habe einen einfachen
useFirstRender
Hook erstellt, um Fälle wie das Fokussieren einer Formulareingabe zu behandeln:import { useRef, useEffect } from 'react'; export function useFirstRender() { const firstRender = useRef(true); useEffect(() => { firstRender.current = false; }, []); return firstRender.current; }
Es beginnt als
true
, wechselt dann zufalse
in dasuseEffect
, das nur einmal und nie wieder läuft.Verwenden Sie es in Ihrer Komponente:
const firstRender = useFirstRender(); const phoneNumberRef = useRef(null); useEffect(() => { if (firstRender || errors.phoneNumber) { phoneNumberRef.current.focus(); } }, [firstRender, errors.phoneNumber]);
Für Ihren Fall würden Sie nur verwenden
if (!firstRender) { ...
.quelle
@ravi, deine ruft die übergebene Unmount-Funktion nicht auf. Hier ist eine etwas vollständigere Version:
/** * Identical to React.useEffect, except that it never runs on mount. This is * the equivalent of the componentDidUpdate lifecycle function. * * @param {function:function} effect - A useEffect effect. * @param {array} [dependencies] - useEffect dependency list. */ export const useEffectExceptOnMount = (effect, dependencies) => { const mounted = React.useRef(false); React.useEffect(() => { if (mounted.current) { const unmount = effect(); return () => unmount && unmount(); } else { mounted.current = true; } }, dependencies); // Reset on unmount for the next mount. React.useEffect(() => { return () => mounted.current = false; }, []); };
quelle
useEffect(() => {...});
dependencies
dass Sie den Parameter beim Aufrufen weglassen .@MehdiDehghani, Ihre Lösung funktioniert einwandfrei. Eine Ergänzung, die Sie tun müssen, ist das Aufheben der Bereitstellung und das Zurücksetzen des
didMount.current
Werts auffalse
. Wenn Sie versuchen, diesen benutzerdefinierten Hook an einer anderen Stelle zu verwenden, erhalten Sie keinen Cache-Wert.import React, { useEffect, useRef } from 'react'; const useDidMountEffect = (func, deps) => { const didMount = useRef(false); useEffect(() => { let unmount; if (didMount.current) unmount = func(); else didMount.current = true; return () => { didMount.current = false; unmount && unmount(); } }, deps); } export default useDidMountEffect;
quelle
false
.