Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Rex Dri
Rex Dri
Commits
5c0d6ab7
Verified
Commit
5c0d6ab7
authored
Apr 12, 2020
by
Florent Chehab
Browse files
feat(hook): tweaked useGlobalReducer
* no more state update on unmounted components
🎉
parent
ef3efc31
Changes
3
Hide whitespace changes
Inline
Side-by-side
frontend/src/hooks/use
Shared
Reducer.js
→
frontend/src/hooks/use
Global
Reducer.js
View file @
5c0d6ab7
import
useGlobalState
from
"
./useGlobalState
"
;
import
{
useCallback
}
from
"
react
"
;
import
useGlobalState
,
{
reduceGlobalState
}
from
"
./useGlobalState
"
;
/**
* Hook that provides
a shared and persistent reducer base state management
* Hook that provides
reducer based globalState access / modification
*
* @param {string} key - id for the state
* @param {function} reducer - Reducer to be used
* @param {*} initialState - initial state value (if not already stored)
*/
function
useSharedReducer
(
key
,
reducer
,
initialState
)
{
const
[
sharedState
,
setSharedState
]
=
useGlobalState
(
key
,
initialState
);
function
useGlobalReducer
(
key
,
reducer
,
initialState
)
{
// useGlobalState will automatically handle the subscription
const
[
sharedState
]
=
useGlobalState
(
key
,
initialState
);
const
[
state
,
dispatch
]
=
useReducer
(
reducer
,
sharedState
);
useEffect
(()
=>
{
setSharedState
(
state
);
},
[
state
,
setSharedState
]);
const
dispatchNotFunction
=
useCallback
(
action
=>
{
if
(
process
.
env
.
NODE_ENV
!==
"
production
"
)
{
const
{
type
}
=
action
;
let
backgroundColor
;
if
(
type
.
includes
(
"
STARTED
"
))
backgroundColor
=
"
cyan
"
;
else
if
(
type
.
includes
(
"
SUCCEEDED
"
))
backgroundColor
=
"
green
"
;
else
if
(
type
.
includes
(
"
INVALIDATED
"
))
backgroundColor
=
"
orange
"
;
else
if
(
type
.
includes
(
"
FAILED
"
))
backgroundColor
=
"
red
"
;
else
backgroundColor
=
"
black
"
;
// eslint-disable-next-line no-console
console
.
log
(
`%c ACTION %c
${
action
.
type
}
`
,
`background:
${
backgroundColor
}
; color: white; font-weight: bold;`
,
""
);
}
dispatch
(
action
);
},
[
dispatch
]
);
const
dispatchNotFunction
=
useCallback
(
action
=>
{
// Will update the global state and trigger setUpdate only on the mounted component
reduceGlobalState
(
key
,
reducer
,
action
);
},
[]);
const
dispatchFunction
=
useCallback
(
action
=>
{
...
...
@@ -59,8 +36,7 @@ function useSharedReducer(key, reducer, initialState) {
[
dispatchFunction
,
dispatchNotFunction
]
);
// make sure to return the saved state to prevent bugs when directly accessing the saved data
return
useMemo
(()
=>
[
sharedState
,
dispatchOut
],
[
sharedState
,
dispatchOut
]);
return
[
sharedState
,
dispatchOut
];
}
export
default
use
Shared
Reducer
;
export
default
use
Global
Reducer
;
frontend/src/hooks/useGlobalState.js
View file @
5c0d6ab7
...
...
@@ -56,6 +56,38 @@ export function updateGlobalState(key, newValue) {
}
}
/**
* Helper to reduce the value in the globalState (identified by a key)
* And trigger an update to all subscribers.
*
* @param key
* @param reducer
* @param action
*/
export
function
reduceGlobalState
(
key
,
reducer
,
action
)
{
if
(
process
.
env
.
NODE_ENV
!==
"
production
"
)
{
const
{
type
}
=
action
;
let
backgroundColor
;
if
(
type
.
includes
(
"
STARTED
"
))
backgroundColor
=
"
cyan
"
;
else
if
(
type
.
includes
(
"
SUCCEEDED
"
))
backgroundColor
=
"
green
"
;
else
if
(
type
.
includes
(
"
INVALIDATED
"
))
backgroundColor
=
"
orange
"
;
else
if
(
type
.
includes
(
"
FAILED
"
))
backgroundColor
=
"
red
"
;
else
backgroundColor
=
"
black
"
;
// eslint-disable-next-line no-console
console
.
log
(
`%c ACTION %c
${
action
.
type
}
`
,
`background:
${
backgroundColor
}
; color: white; font-weight: bold;`
,
""
);
}
const
previousValue
=
getPersistedValue
(
key
);
const
newValue
=
reducer
(
previousValue
,
action
);
updateGlobalState
(
key
,
newValue
);
}
/**
* Gets the latest data retrieved from the api for the key
* @param {string} key - route / sing or plur
...
...
frontend/src/hooks/wrappers/api.js
View file @
5c0d6ab7
import
{
useCallback
,
useMemo
}
from
"
react
"
;
import
use
Shared
Reducer
from
"
../use
Shared
Reducer
"
;
import
use
Global
Reducer
from
"
../use
Global
Reducer
"
;
import
CrudReducers
from
"
../../utils/api/CrudReducers
"
;
import
CrudActions
from
"
../../utils/api/CrudActions
"
;
import
RequestParams
from
"
../../utils/api/RequestParams
"
;
...
...
@@ -19,7 +19,7 @@ export function useApi(route, variant) {
return
[
internal
.
getForOne
(),
CrudReducers
.
defaultOneState
];
},
[]);
const
[
state
,
dispatch
]
=
use
Shared
Reducer
(
const
[
state
,
dispatch
]
=
use
Global
Reducer
(
`api-
${
route
}
-
${
variant
}
`
,
reducer
,
defaultState
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment