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
| 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.
| 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>
)
|