Use useMemo and useCallback to memoize context values

This commit is contained in:
Amine Ben hammou
2020-02-20 04:02:53 +01:00
committed by Jack Kitterhing
parent 2f2a00cbbe
commit c921bc6f71
9 changed files with 69 additions and 52 deletions

View File

@@ -1,5 +0,0 @@
export default function getFeaturesContext(data) {
const flags = data.mailpoet_feature_flags;
const isSupported = (feature) => flags[feature] || false;
return { isSupported };
}

View File

@@ -1,5 +0,0 @@
export default function getSegmentsContext(data) {
return {
all: data.mailpoetSegments,
};
}

View File

@@ -1,5 +0,0 @@
export default function getUsersContext(data) {
return {
isNewUser: data.mailpoet_is_new_user,
};
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
import getFeaturesContext from './getFeaturesContext.jsx';
import getSegmentsContext from './getSegmentsContext.jsx';
import getUsersContext from './getUsersContext.jsx';
import useFeaturesContext from './useFeaturesContext.jsx';
import useSegmentsContext from './useSegmentsContext.jsx';
import useUsersContext from './useUsersContext.jsx';
import useNotices from './useNotices.jsx';
/**
@@ -10,9 +10,9 @@ import useNotices from './useNotices.jsx';
* some React hooks to build some parts of the context.
*/
export function useGlobalContextValue(data) {
const features = getFeaturesContext(data);
const segments = getSegmentsContext(data);
const users = getUsersContext(data);
const features = useFeaturesContext(data);
const segments = useSegmentsContext(data);
const users = useUsersContext(data);
const notices = useNotices();
return {
features, segments, users, notices,

View File

@@ -0,0 +1,9 @@
import React from 'react';
export default function useFeaturesContext(data) {
return React.useMemo(() => {
const flags = data.mailpoet_feature_flags;
const isSupported = (feature) => flags[feature] || false;
return { isSupported };
}, [data]);
}

View File

@@ -4,23 +4,35 @@ export default () => {
const [items, setItems] = React.useState([]);
const [nextId, setNextId] = React.useState(1);
const getNextId = () => {
const getNextId = React.useCallback(() => {
setNextId((x) => x + 1);
return nextId;
};
}, [nextId]);
const add = (item) => {
const add = React.useCallback((item) => {
setItems((xs) => [...xs, { ...item, id: item.id || getNextId() }]);
};
}, [getNextId]);
const remove = (id) => {
const remove = React.useCallback((id) => {
setItems((xs) => xs.filter((x) => x.id !== id));
};
}, []);
const success = (content, props = {}) => add({ ...props, type: 'success', children: content });
const info = (content, props = {}) => add({ ...props, type: 'info', children: content });
const warning = (content, props = {}) => add({ ...props, type: 'warning', children: content });
const error = (content, props = {}) => add({ ...props, type: 'error', children: content });
const success = React.useCallback(
(content, props = {}) => add({ ...props, type: 'success', children: content }),
[add]
);
const info = React.useCallback(
(content, props = {}) => add({ ...props, type: 'info', children: content }),
[add]
);
const warning = React.useCallback(
(content, props = {}) => add({ ...props, type: 'warning', children: content }),
[add]
);
const error = React.useCallback(
(content, props = {}) => add({ ...props, type: 'error', children: content }),
[add]
);
return {
items, success, info, warning, error, remove,

View File

@@ -0,0 +1,7 @@
import React from 'react';
export default function useSegmentsContext(data) {
return React.useMemo(() => ({
all: data.mailpoetSegments,
}), [data]);
}

View File

@@ -0,0 +1,7 @@
import React from 'react';
export default function useUsersContext(data) {
return React.useMemo(() => ({
isNewUser: data.mailpoet_is_new_user,
}), [data]);
}

View File

@@ -7,28 +7,25 @@ import Notices from 'notices/notices.jsx';
const ExperimentalFeatures = () => {
const [flags, setFlags] = useState(null);
const contextValue = useGlobalContextValue(window);
const [mounted, setMounted] = useState(false);
const showError = contextValue.notices.error;
useEffect(() => {
if (!mounted) {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'featureFlags',
action: 'getAll',
}).done((response) => {
const flagsMap = response.data.reduce((obj, item) => ({ ...obj, [item.name]: item }), {});
setFlags(flagsMap);
}).fail((response) => {
if (response.errors.length > 0) {
contextValue.notices.error(
<>{response.errors.map((error) => <p>{error.message}</p>)}</>,
{ scroll: true }
);
}
});
setMounted(true);
}
}, [contextValue.notices, mounted]);
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'featureFlags',
action: 'getAll',
}).done((response) => {
const flagsMap = response.data.reduce((obj, item) => ({ ...obj, [item.name]: item }), {});
setFlags(flagsMap);
}).fail((response) => {
if (response.errors.length > 0) {
showError(
<>{response.errors.map((error) => <p>{error.message}</p>)}</>,
{ scroll: true }
);
}
});
}, [showError]);
function handleChange(event) {
const name = event.target.name;
@@ -49,7 +46,7 @@ const ExperimentalFeatures = () => {
contextValue.notices.success(<p>{message}</p>);
}).fail((response) => {
if (response.errors.length > 0) {
contextValue.notices.error(
showError(
response.errors.map((error) => <p key={error.message}>{error.message}</p>),
{ scroll: true }
);