@@ -10,6 +10,27 @@ import {
1010 PokemonErrorBoundary ,
1111} from '../pokemon'
1212
13+ function useSafeDispatch ( dispatch ) {
14+ const mountedRef = React . useRef ( false )
15+
16+ React . useEffect ( ( ) => {
17+ mountedRef . current = true
18+ // Cleanup function
19+ return ( ) => {
20+ mountedRef . current = false
21+ }
22+ } , [ ] )
23+
24+ return React . useCallback (
25+ ( ...args ) => {
26+ if ( mountedRef . current ) {
27+ dispatch ( ...args )
28+ }
29+ } ,
30+ [ dispatch ] ,
31+ )
32+ }
33+
1334function asyncReducer ( state , action ) {
1435 switch ( action . type ) {
1536 case 'pending' : {
@@ -31,45 +52,44 @@ function asyncReducer(state, action) {
3152}
3253
3354// Custom hook for using async functions with data retreiving.
34- const useAsync = ( asyncCallback , initialState , dependencies ) => {
35- const [ state , dispatch ] = React . useReducer ( asyncReducer , {
55+ const useAsync = initialState => {
56+ const [ state , unsafeDispatch ] = React . useReducer ( asyncReducer , {
3657 status : 'idle' ,
3758 data : null ,
3859 error : null ,
3960 ...initialState ,
4061 } )
41- React . useEffect ( ( ) => {
42- const promise = asyncCallback ( )
43- if ( ! promise ) {
44- return
45- }
46- dispatch ( { type : 'pending' } )
47- promise . then (
48- data => {
49- dispatch ( { type : 'resolved' , data} )
50- } ,
51- error => {
52- dispatch ( { type : 'rejected' , error} )
53- } ,
54- )
55- // eslint-disable-next-line react-hooks/exhaustive-deps
56- } , dependencies )
57- return state
58- }
5962
60- function PokemonInfo ( { pokemonName} ) {
61- // Executing our custom hook.
62- const state = useAsync (
63- ( ) => {
64- if ( ! pokemonName ) {
65- return
66- }
67- return fetchPokemon ( pokemonName )
63+ const dispatch = useSafeDispatch ( unsafeDispatch )
64+
65+ const run = React . useCallback (
66+ promise => {
67+ dispatch ( { type : 'pending' } )
68+ promise . then (
69+ data => {
70+ dispatch ( { type : 'resolved' , data} )
71+ } ,
72+ error => {
73+ dispatch ( { type : 'rejected' , error} )
74+ } ,
75+ )
6876 } ,
69- { status : pokemonName ? 'pending' : 'idle' } ,
70- [ pokemonName ] ,
77+ [ dispatch ] ,
7178 )
72- const { data : pokemon , status, error} = state
79+ return { ...state , run}
80+ }
81+
82+ function PokemonInfo ( { pokemonName} ) {
83+ const { data : pokemon , status, error, run} = useAsync ( {
84+ status : pokemonName ? 'pending' : 'idle' ,
85+ } )
86+
87+ React . useEffect ( ( ) => {
88+ if ( ! pokemonName ) {
89+ return
90+ }
91+ run ( fetchPokemon ( pokemonName ) )
92+ } , [ pokemonName , run ] )
7393
7494 if ( status === 'idle' || ! pokemonName ) {
7595 return 'Submit a pokemon'
0 commit comments