react hooks useEffect() cleanup for only componentWillUnmount?

koo picture koo · Mar 6, 2019 · Viewed 85.7k times · Source

Let me explain the result of this code for asking my issue easily.

const ForExample = () => {
    const [name, setName] = useState('');
    const [username, setUsername] = useState('');

    useEffect(() => {
        console.log('effect');
        console.log({
            name,
            username
        });

        return () => {
            console.log('cleaned up');
            console.log({
                name,
                username
            });
        };
    }, [username]);

    const handleName = e => {
        const { value } = e.target;

        setName(value);
    };

    const handleUsername = e => {
        const { value } = e.target;

        setUsername(value);
    };

    return (
        <div>
            <div>
                <input value={name} onChange={handleName} />
                <input value={username} onChange={handleUsername} />
            </div>
            <div>
                <div>
                    <span>{name}</span>
                </div>
                <div>
                    <span>{username}</span>
                </div>
            </div>
        </div>
    );
};

When the ForExample component mounts, 'effect' will be logged. This is related to the componentDidMount().

And whenever I change name input, both 'effect' and 'cleaned up' will be logged. Vice versa, no message will be logged whenever I change username input since I added [username] to the second parameter of useEffect(). This is related to the componentDidUpdate()

Lastly, when the ForExample component unmounts, 'cleaned up' will be logged. This is related to the componentWillUnmount().

We all know that.

To sum, 'cleaned up' is invoked whenever the component is being re-rendered(includes unmount)

If I want to make this component to log 'cleaned up' for only the moment when it is unmount, I just have to change the second parameter of useEffect() to [].

But If I change [username] to [], ForExample component no longer implements the componentDidUpdate() for name input.

What I want to do is that, to make the component supports both componentDidUpdate() only for name input and componentWillUnmount(). (logging 'cleaned up' for only the moment when the component is being unmounted)

Answer

Mehran Motiee picture Mehran Motiee · Mar 7, 2019

you can use more than one useEffect

for example if my variable is data1 i can use all of this in my component

useEffect( () => console.log("mount"), [] );
useEffect( () => console.log("will update data1"), [ data1 ] );
useEffect( () => console.log("will update any") );
useEffect( () => () => console.log("will update data1 or unmount"), [ data1 ] );
useEffect( () => () => console.log("unmount"), [] );