mirror of
https://github.com/strapi/strapi.git
synced 2025-09-25 08:19:07 +00:00
Fix cleanup in useeffect
Signed-off-by: soupette <cyril.lpz@gmail.com>
This commit is contained in:
parent
62bb0bbae1
commit
16c7d2123f
@ -1,5 +1,5 @@
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useReducer } from 'react';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { get } from 'lodash';
|
||||
import { request, useGlobalContext } from 'strapi-helper-plugin';
|
||||
import PropTypes from 'prop-types';
|
||||
@ -15,11 +15,10 @@ import { crudInitialState, crudReducer } from '../../sharedReducers';
|
||||
import { getRequestUrl } from './utils';
|
||||
|
||||
// This container is used to handle the CRUD
|
||||
const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug }) => {
|
||||
const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug, id, origin }) => {
|
||||
const { emitEvent } = useGlobalContext();
|
||||
const { push, replace } = useHistory();
|
||||
|
||||
const { id, origin } = useParams();
|
||||
const [
|
||||
{ componentsDataStructure, contentTypeDataStructure, data, isLoading, status },
|
||||
dispatch,
|
||||
@ -99,8 +98,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug }) => {
|
||||
});
|
||||
}, [allLayoutData]);
|
||||
|
||||
const shouldFetch = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
const abortController = new AbortController();
|
||||
const { signal } = abortController;
|
||||
@ -139,7 +136,7 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug }) => {
|
||||
}
|
||||
};
|
||||
|
||||
if (requestURL && shouldFetch.current) {
|
||||
if (requestURL) {
|
||||
getData(signal);
|
||||
} else {
|
||||
dispatch({ type: 'INIT_FORM' });
|
||||
@ -147,7 +144,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug }) => {
|
||||
|
||||
return () => {
|
||||
abortController.abort();
|
||||
shouldFetch.current = requestURL === null;
|
||||
};
|
||||
}, [requestURL, push, from, cleanReceivedData, cleanClonedData]);
|
||||
|
||||
@ -315,6 +311,7 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, from, slug }) => {
|
||||
|
||||
CollectionTypeFormWrapper.defaultProps = {
|
||||
from: '/',
|
||||
origin: null,
|
||||
};
|
||||
|
||||
CollectionTypeFormWrapper.propTypes = {
|
||||
@ -335,6 +332,8 @@ CollectionTypeFormWrapper.propTypes = {
|
||||
}).isRequired,
|
||||
children: PropTypes.func.isRequired,
|
||||
from: PropTypes.string,
|
||||
id: PropTypes.string.isRequired,
|
||||
origin: PropTypes.string,
|
||||
slug: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { Switch, Route, useRouteMatch, useParams } from 'react-router-dom';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { get } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import { LoadingIndicatorPage, CheckPagePermissions } from 'strapi-helper-plugin';
|
||||
import pluginPermissions from '../../permissions';
|
||||
import { ContentTypeLayoutContext } from '../../contexts';
|
||||
@ -10,9 +12,12 @@ import EditSettingsView from '../EditSettingsView';
|
||||
import ListView from '../ListView';
|
||||
import ListSettingsView from '../ListSettingsView';
|
||||
|
||||
const CollectionTypeRecursivePath = () => {
|
||||
const { url } = useRouteMatch();
|
||||
const { slug } = useParams();
|
||||
const CollectionTypeRecursivePath = ({
|
||||
match: {
|
||||
params: { slug },
|
||||
url,
|
||||
},
|
||||
}) => {
|
||||
const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug);
|
||||
|
||||
const { rawContentTypeLayout, rawComponentsLayouts } = useMemo(() => {
|
||||
@ -34,12 +39,37 @@ const CollectionTypeRecursivePath = () => {
|
||||
return { rawContentTypeLayout, rawComponentsLayouts };
|
||||
}, [layout]);
|
||||
|
||||
if (isLoading) {
|
||||
const uid = get(layout, ['contentType', 'uid'], null);
|
||||
|
||||
// This statement is needed in order to prevent the CollectionTypeFormWrapper effects clean up phase to be run twice.
|
||||
// What can happen is that when navigating from one entry to another the cleanup phase of the fetch data effect is run twice : once when
|
||||
// unmounting, once when the url changes.
|
||||
// Since it can happen that the layout there's a delay when the layout is being fetched and the url changes adding the uid ! == slug
|
||||
// statement prevent the component from being mounted and unmounted twice.
|
||||
if (uid !== slug || isLoading) {
|
||||
return <LoadingIndicatorPage />;
|
||||
}
|
||||
|
||||
const renderRoute = (_, Component) => {
|
||||
return <Component slug={slug} layout={layout} />;
|
||||
const renderRoute = (
|
||||
{
|
||||
location: { state },
|
||||
history: { goBack },
|
||||
match: {
|
||||
params: { id, origin },
|
||||
},
|
||||
},
|
||||
Component
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
slug={slug}
|
||||
layout={layout}
|
||||
state={state}
|
||||
goBack={goBack}
|
||||
id={id}
|
||||
origin={origin}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const routes = [
|
||||
@ -79,4 +109,13 @@ const CollectionTypeRecursivePath = () => {
|
||||
);
|
||||
};
|
||||
|
||||
CollectionTypeRecursivePath.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
url: PropTypes.string.isRequired,
|
||||
params: PropTypes.shape({
|
||||
slug: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default memo(CollectionTypeRecursivePath);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { memo, useCallback, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get } from 'lodash';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import {
|
||||
BackHeader,
|
||||
LiLink,
|
||||
@ -31,10 +30,8 @@ import DeleteLink from './DeleteLink';
|
||||
import InformationCard from './InformationCard';
|
||||
|
||||
/* eslint-disable react/no-array-index-key */
|
||||
const EditView = ({ isSingleType, layout, slug }) => {
|
||||
const { goBack } = useHistory();
|
||||
const EditView = ({ isSingleType, goBack, layout, slug, state, id, origin }) => {
|
||||
const { currentEnvironment, plugins } = useGlobalContext();
|
||||
const { state } = useLocation();
|
||||
// Permissions
|
||||
const viewPermissions = useMemo(() => generatePermissionsObject(slug), [slug]);
|
||||
const { allowedActions, isLoading: isLoadingForPermissions } = useUserPermissions(
|
||||
@ -59,7 +56,9 @@ const EditView = ({ isSingleType, layout, slug }) => {
|
||||
: pluginPermissions.collectionTypesConfigurations;
|
||||
}, [isSingleType]);
|
||||
|
||||
const configurationsURL = `/plugins/${pluginId}/collectionType/${slug}/configurations/edit`;
|
||||
const configurationsURL = `/plugins/${pluginId}/${
|
||||
isSingleType ? 'singleType' : 'collectionType'
|
||||
}/${slug}/configurations/edit`;
|
||||
const currentContentTypeLayoutData = useMemo(() => get(layout, ['contentType'], {}), [layout]);
|
||||
|
||||
const DataManagementWrapper = useMemo(
|
||||
@ -91,7 +90,7 @@ const EditView = ({ isSingleType, layout, slug }) => {
|
||||
|
||||
// TODO: create a hook to handle/provide the permissions this should be done for the i18n feature
|
||||
return (
|
||||
<DataManagementWrapper allLayoutData={layout} from={from} slug={slug}>
|
||||
<DataManagementWrapper allLayoutData={layout} from={from} slug={slug} id={id} origin={origin}>
|
||||
{({
|
||||
componentsDataStructure,
|
||||
contentTypeDataStructure,
|
||||
@ -264,7 +263,10 @@ const EditView = ({ isSingleType, layout, slug }) => {
|
||||
};
|
||||
|
||||
EditView.defaultProps = {
|
||||
id: null,
|
||||
isSingleType: false,
|
||||
origin: null,
|
||||
state: {},
|
||||
};
|
||||
|
||||
EditView.propTypes = {
|
||||
@ -278,7 +280,11 @@ EditView.propTypes = {
|
||||
attributes: PropTypes.object.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
id: PropTypes.string,
|
||||
isSingleType: PropTypes.bool,
|
||||
goBack: PropTypes.func.isRequired,
|
||||
origin: PropTypes.string,
|
||||
state: PropTypes.object,
|
||||
slug: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,40 @@
|
||||
import React from 'react';
|
||||
import { Switch, Route, useRouteMatch, useParams } from 'react-router-dom';
|
||||
import React, { memo, useMemo } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { LoadingIndicatorPage, CheckPagePermissions } from 'strapi-helper-plugin';
|
||||
import pluginPermissions from '../../permissions';
|
||||
import { ContentTypeLayoutContext } from '../../contexts';
|
||||
import { useFetchContentTypeLayout } from '../../hooks';
|
||||
import { formatLayoutToApi } from '../../utils';
|
||||
import EditView from '../EditView';
|
||||
import EditSettingsView from '../EditSettingsView';
|
||||
|
||||
const SingleTypeRecursivePath = props => {
|
||||
const { url } = useRouteMatch();
|
||||
const { slug } = useParams();
|
||||
const { isLoading, layout } = useFetchContentTypeLayout(slug);
|
||||
const SingleTypeRecursivePath = ({
|
||||
match: {
|
||||
params: { slug },
|
||||
url,
|
||||
},
|
||||
}) => {
|
||||
const { isLoading, layout, updateLayout } = useFetchContentTypeLayout(slug);
|
||||
|
||||
const { rawContentTypeLayout, rawComponentsLayouts } = useMemo(() => {
|
||||
let rawComponentsLayouts = {};
|
||||
let rawContentTypeLayout = {};
|
||||
|
||||
if (layout.contentType) {
|
||||
rawContentTypeLayout = formatLayoutToApi(layout.contentType);
|
||||
}
|
||||
|
||||
if (layout.components) {
|
||||
rawComponentsLayouts = Object.keys(layout.components).reduce((acc, current) => {
|
||||
acc[current] = formatLayoutToApi(layout.components[current]);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return { rawContentTypeLayout, rawComponentsLayouts };
|
||||
}, [layout]);
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingIndicatorPage />;
|
||||
@ -19,21 +43,36 @@ const SingleTypeRecursivePath = props => {
|
||||
return (
|
||||
<ContentTypeLayoutContext.Provider value={layout}>
|
||||
<Switch>
|
||||
<Route path={`${url}/configurations/edit`}>
|
||||
<CheckPagePermissions permissions={pluginPermissions.singleTypesConfigurations}>
|
||||
<EditSettingsView
|
||||
components={rawComponentsLayouts}
|
||||
isContentTypeView
|
||||
mainLayout={rawContentTypeLayout}
|
||||
slug={slug}
|
||||
updateLayout={updateLayout}
|
||||
/>
|
||||
</CheckPagePermissions>
|
||||
</Route>
|
||||
<Route
|
||||
path={`${url}/ctm-configurations/edit-settings/:type`}
|
||||
render={routeProps => (
|
||||
<CheckPagePermissions permissions={pluginPermissions.singleTypesConfigurations}>
|
||||
<EditSettingsView {...props} {...routeProps} slug={slug} />
|
||||
</CheckPagePermissions>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path={`${url}`}
|
||||
render={() => <EditView layout={layout} slug={slug} isSingleType />}
|
||||
path={url}
|
||||
render={({ location: { state }, history: { goBack } }) => {
|
||||
return (
|
||||
<EditView layout={layout} slug={slug} isSingleType state={state} goBack={goBack} />
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</ContentTypeLayoutContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default SingleTypeRecursivePath;
|
||||
SingleTypeRecursivePath.propTypes = {
|
||||
match: PropTypes.shape({
|
||||
url: PropTypes.string.isRequired,
|
||||
params: PropTypes.shape({
|
||||
slug: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
export default memo(SingleTypeRecursivePath);
|
||||
|
Loading…
x
Reference in New Issue
Block a user