@wordpress/server-side-render 3.0.1 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Install the module
|
|
|
18
18
|
npm install @wordpress/server-side-render --save
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for
|
|
21
|
+
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](https://github.com/WordPress/gutenberg/tree/HEAD/packages/babel-preset-default#polyfill) in your code._
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
@@ -58,6 +58,7 @@ The HTTP request method to use, either 'GET' or 'POST'. It's 'GET' by default. T
|
|
|
58
58
|
- Required: No
|
|
59
59
|
|
|
60
60
|
#### Example:
|
|
61
|
+
|
|
61
62
|
```php
|
|
62
63
|
function add_rest_method( $endpoints ) {
|
|
63
64
|
if ( is_wp_version_compatible( '5.5' ) ) {
|
|
@@ -108,9 +109,7 @@ The component is rendered while the API request is being processed (loading stat
|
|
|
108
109
|
|
|
109
110
|
```jsx
|
|
110
111
|
const MyServerSideRender = () => (
|
|
111
|
-
<ServerSideRender
|
|
112
|
-
LoadingResponsePlaceholder={ MyAmazingPlaceholder }
|
|
113
|
-
/>
|
|
112
|
+
<ServerSideRender LoadingResponsePlaceholder={ MyAmazingPlaceholder } />
|
|
114
113
|
);
|
|
115
114
|
```
|
|
116
115
|
|
|
@@ -63,11 +63,26 @@ function DefaultErrorResponsePlaceholder({
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function DefaultLoadingResponsePlaceholder({
|
|
66
|
-
|
|
66
|
+
children,
|
|
67
|
+
showLoader
|
|
67
68
|
}) {
|
|
68
|
-
return (0, _element.createElement)(
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
return (0, _element.createElement)("div", {
|
|
70
|
+
style: {
|
|
71
|
+
position: 'relative'
|
|
72
|
+
}
|
|
73
|
+
}, showLoader && (0, _element.createElement)("div", {
|
|
74
|
+
style: {
|
|
75
|
+
position: 'absolute',
|
|
76
|
+
top: '50%',
|
|
77
|
+
left: '50%',
|
|
78
|
+
marginTop: '-9px',
|
|
79
|
+
marginLeft: '-9px'
|
|
80
|
+
}
|
|
81
|
+
}, (0, _element.createElement)(_components.Spinner, null)), (0, _element.createElement)("div", {
|
|
82
|
+
style: {
|
|
83
|
+
opacity: showLoader ? '0.3' : 1
|
|
84
|
+
}
|
|
85
|
+
}, children));
|
|
71
86
|
}
|
|
72
87
|
|
|
73
88
|
function ServerSideRender(props) {
|
|
@@ -82,19 +97,18 @@ function ServerSideRender(props) {
|
|
|
82
97
|
LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
|
|
83
98
|
} = props;
|
|
84
99
|
const isMountedRef = (0, _element.useRef)(true);
|
|
100
|
+
const [showLoader, setShowLoader] = (0, _element.useState)(false);
|
|
85
101
|
const fetchRequestRef = (0, _element.useRef)();
|
|
86
102
|
const [response, setResponse] = (0, _element.useState)(null);
|
|
87
103
|
const prevProps = (0, _compose.usePrevious)(props);
|
|
104
|
+
const [isLoading, setIsLoading] = (0, _element.useState)(false);
|
|
88
105
|
|
|
89
106
|
function fetchData() {
|
|
90
107
|
if (!isMountedRef.current) {
|
|
91
108
|
return;
|
|
92
109
|
}
|
|
93
110
|
|
|
94
|
-
|
|
95
|
-
setResponse(null);
|
|
96
|
-
}
|
|
97
|
-
|
|
111
|
+
setIsLoading(true);
|
|
98
112
|
const sanitizedAttributes = attributes && (0, _blocks.__experimentalSanitizeBlockAttributes)(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
|
|
99
113
|
// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
|
|
100
114
|
|
|
@@ -121,6 +135,10 @@ function ServerSideRender(props) {
|
|
|
121
135
|
errorMsg: error.message
|
|
122
136
|
});
|
|
123
137
|
}
|
|
138
|
+
}).finally(() => {
|
|
139
|
+
if (isMountedRef.current && fetchRequest === fetchRequestRef.current) {
|
|
140
|
+
setIsLoading(false);
|
|
141
|
+
}
|
|
124
142
|
});
|
|
125
143
|
return fetchRequest;
|
|
126
144
|
}
|
|
@@ -140,17 +158,44 @@ function ServerSideRender(props) {
|
|
|
140
158
|
debouncedFetchData();
|
|
141
159
|
}
|
|
142
160
|
});
|
|
161
|
+
/**
|
|
162
|
+
* Effect to handle showing the loading placeholder.
|
|
163
|
+
* Show it only if there is no previous response or
|
|
164
|
+
* the request takes more than one second.
|
|
165
|
+
*/
|
|
143
166
|
|
|
144
|
-
|
|
167
|
+
(0, _element.useEffect)(() => {
|
|
168
|
+
if (!isLoading) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const timeout = setTimeout(() => {
|
|
173
|
+
setShowLoader(true);
|
|
174
|
+
}, 1000);
|
|
175
|
+
return () => clearTimeout(timeout);
|
|
176
|
+
}, [isLoading]);
|
|
177
|
+
const hasResponse = !!response;
|
|
178
|
+
const hasEmptyResponse = response === '';
|
|
179
|
+
const hasError = response === null || response === void 0 ? void 0 : response.error;
|
|
180
|
+
|
|
181
|
+
if (hasEmptyResponse || !hasResponse) {
|
|
145
182
|
return (0, _element.createElement)(EmptyResponsePlaceholder, props);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (hasError) {
|
|
149
186
|
return (0, _element.createElement)(ErrorResponsePlaceholder, (0, _extends2.default)({
|
|
150
187
|
response: response
|
|
151
188
|
}, props));
|
|
152
189
|
}
|
|
153
190
|
|
|
191
|
+
if (isLoading) {
|
|
192
|
+
return (0, _element.createElement)(LoadingResponsePlaceholder, (0, _extends2.default)({}, props, {
|
|
193
|
+
showLoader: showLoader
|
|
194
|
+
}), hasResponse && (0, _element.createElement)(_element.RawHTML, {
|
|
195
|
+
className: className
|
|
196
|
+
}, response));
|
|
197
|
+
}
|
|
198
|
+
|
|
154
199
|
return (0, _element.createElement)(_element.RawHTML, {
|
|
155
200
|
className: className
|
|
156
201
|
}, response);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","fetchRequestRef","setResponse","prevProps","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","debouncedFetchData","undefined"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t<Spinner />\n\t\t</Placeholder>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( null !== response ) {\n\t\t\tsetResponse( null );\n\t\t}\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\tif ( response === '' ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t} else if ( ! response ) {\n\t\treturn <LoadingResponsePlaceholder { ...props } />;\n\t} else if ( response.error ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
|
|
@@ -46,11 +46,26 @@ function DefaultErrorResponsePlaceholder({
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
function DefaultLoadingResponsePlaceholder({
|
|
49
|
-
|
|
49
|
+
children,
|
|
50
|
+
showLoader
|
|
50
51
|
}) {
|
|
51
|
-
return createElement(
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
return createElement("div", {
|
|
53
|
+
style: {
|
|
54
|
+
position: 'relative'
|
|
55
|
+
}
|
|
56
|
+
}, showLoader && createElement("div", {
|
|
57
|
+
style: {
|
|
58
|
+
position: 'absolute',
|
|
59
|
+
top: '50%',
|
|
60
|
+
left: '50%',
|
|
61
|
+
marginTop: '-9px',
|
|
62
|
+
marginLeft: '-9px'
|
|
63
|
+
}
|
|
64
|
+
}, createElement(Spinner, null)), createElement("div", {
|
|
65
|
+
style: {
|
|
66
|
+
opacity: showLoader ? '0.3' : 1
|
|
67
|
+
}
|
|
68
|
+
}, children));
|
|
54
69
|
}
|
|
55
70
|
|
|
56
71
|
export default function ServerSideRender(props) {
|
|
@@ -65,18 +80,18 @@ export default function ServerSideRender(props) {
|
|
|
65
80
|
LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
|
|
66
81
|
} = props;
|
|
67
82
|
const isMountedRef = useRef(true);
|
|
83
|
+
const [showLoader, setShowLoader] = useState(false);
|
|
68
84
|
const fetchRequestRef = useRef();
|
|
69
85
|
const [response, setResponse] = useState(null);
|
|
70
86
|
const prevProps = usePrevious(props);
|
|
87
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
71
88
|
|
|
72
89
|
function fetchData() {
|
|
73
90
|
if (!isMountedRef.current) {
|
|
74
91
|
return;
|
|
75
92
|
}
|
|
76
93
|
|
|
77
|
-
|
|
78
|
-
setResponse(null);
|
|
79
|
-
}
|
|
94
|
+
setIsLoading(true);
|
|
80
95
|
|
|
81
96
|
const sanitizedAttributes = attributes && __experimentalSanitizeBlockAttributes(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
|
|
82
97
|
// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
|
|
@@ -105,6 +120,10 @@ export default function ServerSideRender(props) {
|
|
|
105
120
|
errorMsg: error.message
|
|
106
121
|
});
|
|
107
122
|
}
|
|
123
|
+
}).finally(() => {
|
|
124
|
+
if (isMountedRef.current && fetchRequest === fetchRequestRef.current) {
|
|
125
|
+
setIsLoading(false);
|
|
126
|
+
}
|
|
108
127
|
});
|
|
109
128
|
return fetchRequest;
|
|
110
129
|
}
|
|
@@ -124,17 +143,44 @@ export default function ServerSideRender(props) {
|
|
|
124
143
|
debouncedFetchData();
|
|
125
144
|
}
|
|
126
145
|
});
|
|
146
|
+
/**
|
|
147
|
+
* Effect to handle showing the loading placeholder.
|
|
148
|
+
* Show it only if there is no previous response or
|
|
149
|
+
* the request takes more than one second.
|
|
150
|
+
*/
|
|
127
151
|
|
|
128
|
-
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (!isLoading) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const timeout = setTimeout(() => {
|
|
158
|
+
setShowLoader(true);
|
|
159
|
+
}, 1000);
|
|
160
|
+
return () => clearTimeout(timeout);
|
|
161
|
+
}, [isLoading]);
|
|
162
|
+
const hasResponse = !!response;
|
|
163
|
+
const hasEmptyResponse = response === '';
|
|
164
|
+
const hasError = response === null || response === void 0 ? void 0 : response.error;
|
|
165
|
+
|
|
166
|
+
if (hasEmptyResponse || !hasResponse) {
|
|
129
167
|
return createElement(EmptyResponsePlaceholder, props);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (hasError) {
|
|
133
171
|
return createElement(ErrorResponsePlaceholder, _extends({
|
|
134
172
|
response: response
|
|
135
173
|
}, props));
|
|
136
174
|
}
|
|
137
175
|
|
|
176
|
+
if (isLoading) {
|
|
177
|
+
return createElement(LoadingResponsePlaceholder, _extends({}, props, {
|
|
178
|
+
showLoader: showLoader
|
|
179
|
+
}), hasResponse && createElement(RawHTML, {
|
|
180
|
+
className: className
|
|
181
|
+
}, response));
|
|
182
|
+
}
|
|
183
|
+
|
|
138
184
|
return createElement(RawHTML, {
|
|
139
185
|
className: className
|
|
140
186
|
}, response);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["isEqual","useDebounce","usePrevious","RawHTML","useEffect","useRef","useState","__","sprintf","apiFetch","addQueryArgs","Placeholder","Spinner","__experimentalSanitizeBlockAttributes","rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","fetchRequestRef","setResponse","prevProps","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","debouncedFetchData","undefined"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t<Spinner />\n\t\t</Placeholder>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( null !== response ) {\n\t\t\tsetResponse( null );\n\t\t}\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\tif ( response === '' ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t} else if ( ! response ) {\n\t\treturn <LoadingResponsePlaceholder { ...props } />;\n\t} else if ( response.error ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/server-side-render/src/server-side-render.js"],"names":["isEqual","useDebounce","usePrevious","RawHTML","useEffect","useRef","useState","__","sprintf","apiFetch","addQueryArgs","Placeholder","Spinner","__experimentalSanitizeBlockAttributes","rendererPath","block","attributes","urlQueryArgs","context","DefaultEmptyResponsePlaceholder","className","DefaultErrorResponsePlaceholder","response","errorMessage","errorMsg","DefaultLoadingResponsePlaceholder","children","showLoader","position","top","left","marginTop","marginLeft","opacity","ServerSideRender","props","httpMethod","EmptyResponsePlaceholder","ErrorResponsePlaceholder","LoadingResponsePlaceholder","isMountedRef","setShowLoader","fetchRequestRef","setResponse","prevProps","isLoading","setIsLoading","fetchData","current","sanitizedAttributes","isPostRequest","urlAttributes","path","data","fetchRequest","method","then","fetchResponse","rendered","catch","error","message","finally","debouncedFetchData","undefined","timeout","setTimeout","clearTimeout","hasResponse","hasEmptyResponse","hasError"],"mappings":"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","sourcesContent":["/**\n * External dependencies\n */\nimport { isEqual } from 'lodash';\n\n/**\n * WordPress dependencies\n */\nimport { useDebounce, usePrevious } from '@wordpress/compose';\nimport { RawHTML, useEffect, useRef, useState } from '@wordpress/element';\nimport { __, sprintf } from '@wordpress/i18n';\nimport apiFetch from '@wordpress/api-fetch';\nimport { addQueryArgs } from '@wordpress/url';\nimport { Placeholder, Spinner } from '@wordpress/components';\nimport { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';\n\nexport function rendererPath( block, attributes = null, urlQueryArgs = {} ) {\n\treturn addQueryArgs( `/wp/v2/block-renderer/${ block }`, {\n\t\tcontext: 'edit',\n\t\t...( null !== attributes ? { attributes } : {} ),\n\t\t...urlQueryArgs,\n\t} );\n}\n\nfunction DefaultEmptyResponsePlaceholder( { className } ) {\n\treturn (\n\t\t<Placeholder className={ className }>\n\t\t\t{ __( 'Block rendered as empty.' ) }\n\t\t</Placeholder>\n\t);\n}\n\nfunction DefaultErrorResponsePlaceholder( { response, className } ) {\n\tconst errorMessage = sprintf(\n\t\t// translators: %s: error message describing the problem\n\t\t__( 'Error loading block: %s' ),\n\t\tresponse.errorMsg\n\t);\n\treturn <Placeholder className={ className }>{ errorMessage }</Placeholder>;\n}\n\nfunction DefaultLoadingResponsePlaceholder( { children, showLoader } ) {\n\treturn (\n\t\t<div style={ { position: 'relative' } }>\n\t\t\t{ showLoader && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t\ttop: '50%',\n\t\t\t\t\t\tleft: '50%',\n\t\t\t\t\t\tmarginTop: '-9px',\n\t\t\t\t\t\tmarginLeft: '-9px',\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t<Spinner />\n\t\t\t\t</div>\n\t\t\t) }\n\t\t\t<div style={ { opacity: showLoader ? '0.3' : 1 } }>\n\t\t\t\t{ children }\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport default function ServerSideRender( props ) {\n\tconst {\n\t\tattributes,\n\t\tblock,\n\t\tclassName,\n\t\thttpMethod = 'GET',\n\t\turlQueryArgs,\n\t\tEmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,\n\t\tErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,\n\t\tLoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,\n\t} = props;\n\n\tconst isMountedRef = useRef( true );\n\tconst [ showLoader, setShowLoader ] = useState( false );\n\tconst fetchRequestRef = useRef();\n\tconst [ response, setResponse ] = useState( null );\n\tconst prevProps = usePrevious( props );\n\tconst [ isLoading, setIsLoading ] = useState( false );\n\n\tfunction fetchData() {\n\t\tif ( ! isMountedRef.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetIsLoading( true );\n\n\t\tconst sanitizedAttributes =\n\t\t\tattributes &&\n\t\t\t__experimentalSanitizeBlockAttributes( block, attributes );\n\n\t\t// If httpMethod is 'POST', send the attributes in the request body instead of the URL.\n\t\t// This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.\n\t\tconst isPostRequest = 'POST' === httpMethod;\n\t\tconst urlAttributes = isPostRequest\n\t\t\t? null\n\t\t\t: sanitizedAttributes ?? null;\n\t\tconst path = rendererPath( block, urlAttributes, urlQueryArgs );\n\t\tconst data = isPostRequest\n\t\t\t? { attributes: sanitizedAttributes ?? null }\n\t\t\t: null;\n\n\t\t// Store the latest fetch request so that when we process it, we can\n\t\t// check if it is the current request, to avoid race conditions on slow networks.\n\t\tconst fetchRequest = ( fetchRequestRef.current = apiFetch( {\n\t\t\tpath,\n\t\t\tdata,\n\t\t\tmethod: isPostRequest ? 'POST' : 'GET',\n\t\t} )\n\t\t\t.then( ( fetchResponse ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current &&\n\t\t\t\t\tfetchResponse\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( fetchResponse.rendered );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.catch( ( error ) => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetResponse( {\n\t\t\t\t\t\terror: true,\n\t\t\t\t\t\terrorMsg: error.message,\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.finally( () => {\n\t\t\t\tif (\n\t\t\t\t\tisMountedRef.current &&\n\t\t\t\t\tfetchRequest === fetchRequestRef.current\n\t\t\t\t) {\n\t\t\t\t\tsetIsLoading( false );\n\t\t\t\t}\n\t\t\t} ) );\n\n\t\treturn fetchRequest;\n\t}\n\n\tconst debouncedFetchData = useDebounce( fetchData, 500 );\n\n\t// When the component unmounts, set isMountedRef to false. This will\n\t// let the async fetch callbacks know when to stop.\n\tuseEffect(\n\t\t() => () => {\n\t\t\tisMountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tuseEffect( () => {\n\t\t// Don't debounce the first fetch. This ensures that the first render\n\t\t// shows data as soon as possible\n\t\tif ( prevProps === undefined ) {\n\t\t\tfetchData();\n\t\t} else if ( ! isEqual( prevProps, props ) ) {\n\t\t\tdebouncedFetchData();\n\t\t}\n\t} );\n\n\t/**\n\t * Effect to handle showing the loading placeholder.\n\t * Show it only if there is no previous response or\n\t * the request takes more than one second.\n\t */\n\tuseEffect( () => {\n\t\tif ( ! isLoading ) {\n\t\t\treturn;\n\t\t}\n\t\tconst timeout = setTimeout( () => {\n\t\t\tsetShowLoader( true );\n\t\t}, 1000 );\n\t\treturn () => clearTimeout( timeout );\n\t}, [ isLoading ] );\n\n\tconst hasResponse = !! response;\n\tconst hasEmptyResponse = response === '';\n\tconst hasError = response?.error;\n\n\tif ( hasEmptyResponse || ! hasResponse ) {\n\t\treturn <EmptyResponsePlaceholder { ...props } />;\n\t}\n\n\tif ( hasError ) {\n\t\treturn <ErrorResponsePlaceholder response={ response } { ...props } />;\n\t}\n\n\tif ( isLoading ) {\n\t\treturn (\n\t\t\t<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>\n\t\t\t\t{ hasResponse && (\n\t\t\t\t\t<RawHTML className={ className }>{ response }</RawHTML>\n\t\t\t\t) }\n\t\t\t</LoadingResponsePlaceholder>\n\t\t);\n\t}\n\n\treturn <RawHTML className={ className }>{ response }</RawHTML>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/server-side-render",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.5",
|
|
4
4
|
"description": "The component used with WordPress to server-side render a preview of dynamic blocks to display in the editor.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -27,19 +27,19 @@
|
|
|
27
27
|
"react-native": "src/index",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@babel/runtime": "^7.13.10",
|
|
30
|
-
"@wordpress/api-fetch": "^5.2.
|
|
31
|
-
"@wordpress/blocks": "^11.
|
|
32
|
-
"@wordpress/components": "^
|
|
33
|
-
"@wordpress/compose": "^5.0.
|
|
34
|
-
"@wordpress/data": "^6.
|
|
35
|
-
"@wordpress/deprecated": "^3.2.
|
|
36
|
-
"@wordpress/element": "^4.0.
|
|
37
|
-
"@wordpress/i18n": "^4.2.
|
|
38
|
-
"@wordpress/url": "^3.
|
|
30
|
+
"@wordpress/api-fetch": "^5.2.5",
|
|
31
|
+
"@wordpress/blocks": "^11.1.3",
|
|
32
|
+
"@wordpress/components": "^19.0.1",
|
|
33
|
+
"@wordpress/compose": "^5.0.5",
|
|
34
|
+
"@wordpress/data": "^6.1.3",
|
|
35
|
+
"@wordpress/deprecated": "^3.2.2",
|
|
36
|
+
"@wordpress/element": "^4.0.3",
|
|
37
|
+
"@wordpress/i18n": "^4.2.3",
|
|
38
|
+
"@wordpress/url": "^3.3.0",
|
|
39
39
|
"lodash": "^4.17.21"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "393c2b5533837fd637e998d23f0124c081a10df0"
|
|
45
45
|
}
|
|
@@ -39,11 +39,26 @@ function DefaultErrorResponsePlaceholder( { response, className } ) {
|
|
|
39
39
|
return <Placeholder className={ className }>{ errorMessage }</Placeholder>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function DefaultLoadingResponsePlaceholder( {
|
|
42
|
+
function DefaultLoadingResponsePlaceholder( { children, showLoader } ) {
|
|
43
43
|
return (
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
<div style={ { position: 'relative' } }>
|
|
45
|
+
{ showLoader && (
|
|
46
|
+
<div
|
|
47
|
+
style={ {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
top: '50%',
|
|
50
|
+
left: '50%',
|
|
51
|
+
marginTop: '-9px',
|
|
52
|
+
marginLeft: '-9px',
|
|
53
|
+
} }
|
|
54
|
+
>
|
|
55
|
+
<Spinner />
|
|
56
|
+
</div>
|
|
57
|
+
) }
|
|
58
|
+
<div style={ { opacity: showLoader ? '0.3' : 1 } }>
|
|
59
|
+
{ children }
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
47
62
|
);
|
|
48
63
|
}
|
|
49
64
|
|
|
@@ -60,17 +75,18 @@ export default function ServerSideRender( props ) {
|
|
|
60
75
|
} = props;
|
|
61
76
|
|
|
62
77
|
const isMountedRef = useRef( true );
|
|
78
|
+
const [ showLoader, setShowLoader ] = useState( false );
|
|
63
79
|
const fetchRequestRef = useRef();
|
|
64
80
|
const [ response, setResponse ] = useState( null );
|
|
65
81
|
const prevProps = usePrevious( props );
|
|
82
|
+
const [ isLoading, setIsLoading ] = useState( false );
|
|
66
83
|
|
|
67
84
|
function fetchData() {
|
|
68
85
|
if ( ! isMountedRef.current ) {
|
|
69
86
|
return;
|
|
70
87
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
88
|
+
|
|
89
|
+
setIsLoading( true );
|
|
74
90
|
|
|
75
91
|
const sanitizedAttributes =
|
|
76
92
|
attributes &&
|
|
@@ -113,6 +129,14 @@ export default function ServerSideRender( props ) {
|
|
|
113
129
|
errorMsg: error.message,
|
|
114
130
|
} );
|
|
115
131
|
}
|
|
132
|
+
} )
|
|
133
|
+
.finally( () => {
|
|
134
|
+
if (
|
|
135
|
+
isMountedRef.current &&
|
|
136
|
+
fetchRequest === fetchRequestRef.current
|
|
137
|
+
) {
|
|
138
|
+
setIsLoading( false );
|
|
139
|
+
}
|
|
116
140
|
} ) );
|
|
117
141
|
|
|
118
142
|
return fetchRequest;
|
|
@@ -139,13 +163,42 @@ export default function ServerSideRender( props ) {
|
|
|
139
163
|
}
|
|
140
164
|
} );
|
|
141
165
|
|
|
142
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Effect to handle showing the loading placeholder.
|
|
168
|
+
* Show it only if there is no previous response or
|
|
169
|
+
* the request takes more than one second.
|
|
170
|
+
*/
|
|
171
|
+
useEffect( () => {
|
|
172
|
+
if ( ! isLoading ) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const timeout = setTimeout( () => {
|
|
176
|
+
setShowLoader( true );
|
|
177
|
+
}, 1000 );
|
|
178
|
+
return () => clearTimeout( timeout );
|
|
179
|
+
}, [ isLoading ] );
|
|
180
|
+
|
|
181
|
+
const hasResponse = !! response;
|
|
182
|
+
const hasEmptyResponse = response === '';
|
|
183
|
+
const hasError = response?.error;
|
|
184
|
+
|
|
185
|
+
if ( hasEmptyResponse || ! hasResponse ) {
|
|
143
186
|
return <EmptyResponsePlaceholder { ...props } />;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if ( hasError ) {
|
|
147
190
|
return <ErrorResponsePlaceholder response={ response } { ...props } />;
|
|
148
191
|
}
|
|
149
192
|
|
|
193
|
+
if ( isLoading ) {
|
|
194
|
+
return (
|
|
195
|
+
<LoadingResponsePlaceholder { ...props } showLoader={ showLoader }>
|
|
196
|
+
{ hasResponse && (
|
|
197
|
+
<RawHTML className={ className }>{ response }</RawHTML>
|
|
198
|
+
) }
|
|
199
|
+
</LoadingResponsePlaceholder>
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
150
203
|
return <RawHTML className={ className }>{ response }</RawHTML>;
|
|
151
204
|
}
|