Skip to content

07 RN - UseEffect

useEffect

  • The Effect Hook, useEffect, adds the ability to perform side effects from a function component.
  • It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes. useEffect runs after every render.

useEffect - no cleanup

useEffect runs after every render. Has access to state/prop variables.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import React, { useState, useEffect } from 'react';

const Home = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        document.title = `You clicked ${count} times`;
    });

    return (
        <>
            <h1>Home {count}</h1>
            <button onClick={() => setCount(count + 1)}>Add 1</button>
        </>
    );
}

export default Home;

useEffect – cleanup

1
useEffect(effect: React.EffectCallback, deps?: React.DependencyList | undefined): void
  • If you need to call some function to clean up – return the callback function from the useEffect().
  • Same code that sould run from componentWillUnmount() class lifecycle method.


  • useEffect can be used several times – split unrelated logic.
  • NB! – pass second parameter – array of variables that are used in effect logic – to let React decide should useEffect run. If values are same between renders - effect will not run.
1
2
3
4
5
6
useEffect(() => { 
    API.subscribe();
    return function cleanup() { 
        API.unsubscribe() 
    } 
})

Returned function will run after previous render.

useEffect - cleanup - Axios example

  • Do not update component when it is unloaded
  • Cancel Axios request
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function Example(props) {
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        let mounted = true;

        fetchAPI.then(() => {
            if (mounted) {
                setLoading(false);
            }
        })

        return function cleanup() {
            mounted = false;
        }
    }, [])

    return <div>{loading ? <p>loading...</p> : <p>loaded</p>}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
useEffect(() => {
    const source = axios.CancelToken.source();

    const fetchUsers = async () => {
        try {
            await Axios.get('/users', {
                cancelToken: source.token
            })
            // ...
        } catch (error) {
            if (Axios.isCancel(error)) {

            } else {
                throw error;
            }
        }
    }

    fetchUsers();

    return () => {
        source.cancel();
    }
}, [])

Axios based example - func, hooks

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const GpsSessions = () => {
    const [items, setItems] = useState([] as IGpsSession[]);

    useEffect(() => {
        const fetchData = async () => setItems(await GpsSessionsApi.getAll());
        fetchData();
    });

    return (
        <>
            <h1>Gps Sessions</h1>
            <table className="table table-striped">
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Name</th>
                        <th>Description</th>
                        <th>Recorded At</th>
                        <th>Locations</th>
                        <th>User</th>
                    </tr>
                </thead>
                <tbody>
                    {items.map(gpsSession => <RowDisplay gpsSession={gpsSession} />)}
                </tbody>
            </table>
        </>
    );
}

export default GpsSessions;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import React, { useState, useEffect } from 'react';
import { IGpsSession } from '../domain/IGpsSession';
import { GpsSessionsApi } from '../services/GpsSessionApi';

const RowDisplay = (props: { gpsSession: IGpsSession }) => (
    <tr key={props.gpsSession.id}>
        <td>{props.gpsSession.id}</td>
        <td>{props.gpsSession.name}</td>
        <td>{props.gpsSession.description}</td>
        <td>{props.gpsSession.recordedAt}</td>
        <td>{props.gpsSession.gpsLocationsCount}</td>
        <td>{props.gpsSession.userFirstLastName}</td>
    </tr>
)