componentWillReceiveProps, componentDidUpdate for React Hook
Solution 1:
The react hook equivalent to the old componentWillReceive
props can be done using the useEffect
hook, just specifying the prop that we want to listen for changes in the dependency array.
I.e:
export default (props) => {
useEffect( () => {
console.log('counter updated');
}, [props.counter])
return <div>Hi {props.counter}</div>
}
For componentDidUpdate
just by omitting the dependency array, the useEffect
function will be called after every re-render.
I.e:
export default (props) => {
useEffect( () => {
console.log('counter updated');
})
return <div>Hi {props.counter}</div>
}
Solution 2:
You can use the useMemo
hook to store a calculation and put props.count
in the array given as second argument to recalculate the value when it changes.
const { useState, useEffect, useMemo } = React;
function App() {
const [count, setCount] = useState(50);
useEffect(() => {
setTimeout(() => {
setCount(150);
}, 2000);
}, []);
return <DisplayCount count={count} />;
}
function DisplayCount(props) {
const count = useMemo(() => props.count > 100 ? 100 : props.count, [props.count]);
return <div> {count} </div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The easiest way to do separate effects when separate props change is to create multiple useEffect
hooks that are only run when one of the separate props change.
const { useState, useEffect } = React;
function App() {
const [groupName, setGroupName] = useState('foo');
const [companyName, setCompanyName] = useState('foo');
useEffect(() => {
setTimeout(() => {
setGroupName('bar');
}, 1000);
setTimeout(() => {
setCompanyName('bar');
}, 2000);
}, []);
return <DisplayGroupCompany groupName={groupName} companyName={companyName} />;
}
function DisplayGroupCompany(props) {
useEffect(() => {
console.log("Let's say, I do want to do some task here only when groupName differs");
}, [props.groupName])
useEffect(() => {
console.log("Let's say,I do want to do some different task here only when companyName differs");
}, [props.companyName])
return <div> {props.groupName} - {props.companyName} </div>;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Solution 3:
If you use the useMemo hook on top of your component and have it dependent on all your props, it runs before everything everytime props change. useEffect is triggered after the updated render and since dependent on all props it triggers after a rerender depending on all props.
const Component = (...props) => {
// useState, useReducer if have
useMemo(() => {
// componentWillReceiveProps
},[...props]);
// ...other logic and stuff
useEffect(() => {
// componentDidUpdate
}, [...props]);
};