@wordpress/server-side-render 3.0.2 → 3.0.6

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 ES2015+ such as IE browsers then using [core-js](https://github.com/zloirock/core-js) will add polyfills for these methods._
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
 
package/build/index.js CHANGED
@@ -49,11 +49,12 @@ const ExportedServerSideRender = (0, _data.withSelect)(select => {
49
49
  }
50
50
 
51
51
  return EMPTY_OBJECT;
52
- })(({
53
- urlQueryArgs = EMPTY_OBJECT,
54
- currentPostId,
55
- ...props
56
- }) => {
52
+ })(_ref => {
53
+ let {
54
+ urlQueryArgs = EMPTY_OBJECT,
55
+ currentPostId,
56
+ ...props
57
+ } = _ref;
57
58
  const newUrlQueryArgs = (0, _element.useMemo)(() => {
58
59
  if (!currentPostId) {
59
60
  return urlQueryArgs;
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/server-side-render/src/index.js"],"names":["EMPTY_OBJECT","ExportedServerSideRender","select","coreEditorSelect","currentPostId","getCurrentPostId","urlQueryArgs","props","newUrlQueryArgs","post_id","window","wp","components","ServerSideRender","ref","since","alternative"],"mappings":";;;;;;;;;AAGA;;;;AACA;;AACA;;AAKA;;AAVA;AACA;AACA;;AAKA;AACA;AACA;;AAGA;AACA;AACA;AACA,MAAMA,YAAY,GAAG,EAArB;AAEA,MAAMC,wBAAwB,GAAG,sBAAcC,MAAF,IAAc;AAC1D;AACA;AACA;AACA,QAAMC,gBAAgB,GAAGD,MAAM,CAAE,aAAF,CAA/B;;AACA,MAAKC,gBAAL,EAAwB;AACvB,UAAMC,aAAa,GAAGD,gBAAgB,CAACE,gBAAjB,EAAtB,CADuB,CAEvB;AACA;AACA;AACA;;AACA,QAAKD,aAAa,IAAI,OAAOA,aAAP,KAAyB,QAA/C,EAA0D;AACzD,aAAO;AACNA,QAAAA;AADM,OAAP;AAGA;AACD;;AACD,SAAOJ,YAAP;AACA,CAlBgC,EAkB5B,CAAE;AAAEM,EAAAA,YAAY,GAAGN,YAAjB;AAA+BI,EAAAA,aAA/B;AAA8C,KAAGG;AAAjD,CAAF,KAAgE;AACpE,QAAMC,eAAe,GAAG,sBAAS,MAAM;AACtC,QAAK,CAAEJ,aAAP,EAAuB;AACtB,aAAOE,YAAP;AACA;;AACD,WAAO;AACNG,MAAAA,OAAO,EAAEL,aADH;AAEN,SAAGE;AAFG,KAAP;AAIA,GARuB,EAQrB,CAAEF,aAAF,EAAiBE,YAAjB,CARqB,CAAxB;AAUA,SAAO,4BAAC,yBAAD;AAAkB,IAAA,YAAY,EAAGE;AAAjC,KAAwDD,KAAxD,EAAP;AACA,CA9BgC,CAAjC;;AAgCA,IAAKG,MAAM,IAAIA,MAAM,CAACC,EAAjB,IAAuBD,MAAM,CAACC,EAAP,CAAUC,UAAtC,EAAmD;AAClDF,EAAAA,MAAM,CAACC,EAAP,CAAUC,UAAV,CAAqBC,gBAArB,GAAwC,yBAAY,CAAEN,KAAF,EAASO,GAAT,KAAkB;AACrE,6BAAY,gCAAZ,EAA8C;AAC7CC,MAAAA,KAAK,EAAE,KADsC;AAE7CC,MAAAA,WAAW,EAAE;AAFgC,KAA9C;AAIA,WAAO,4BAAC,wBAAD,6BAA+BT,KAA/B;AAAuC,MAAA,GAAG,EAAGO;AAA7C,OAAP;AACA,GANuC,CAAxC;AAOA;;eAEcb,wB","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, forwardRef } from '@wordpress/element';\nimport { withSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport ServerSideRender from './server-side-render';\n\n/**\n * Constants\n */\nconst EMPTY_OBJECT = {};\n\nconst ExportedServerSideRender = withSelect( ( select ) => {\n\t// FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.\n\t// It is used by blocks that can be loaded into a *non-post* block editor.\n\t// eslint-disable-next-line @wordpress/data-no-store-string-literals\n\tconst coreEditorSelect = select( 'core/editor' );\n\tif ( coreEditorSelect ) {\n\t\tconst currentPostId = coreEditorSelect.getCurrentPostId();\n\t\t// For templates and template parts we use a custom ID format.\n\t\t// Since they aren't real posts, we don't want to use their ID\n\t\t// for server-side rendering. Since they use a string based ID,\n\t\t// we can assume real post IDs are numbers.\n\t\tif ( currentPostId && typeof currentPostId === 'number' ) {\n\t\t\treturn {\n\t\t\t\tcurrentPostId,\n\t\t\t};\n\t\t}\n\t}\n\treturn EMPTY_OBJECT;\n} )( ( { urlQueryArgs = EMPTY_OBJECT, currentPostId, ...props } ) => {\n\tconst newUrlQueryArgs = useMemo( () => {\n\t\tif ( ! currentPostId ) {\n\t\t\treturn urlQueryArgs;\n\t\t}\n\t\treturn {\n\t\t\tpost_id: currentPostId,\n\t\t\t...urlQueryArgs,\n\t\t};\n\t}, [ currentPostId, urlQueryArgs ] );\n\n\treturn <ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />;\n} );\n\nif ( window && window.wp && window.wp.components ) {\n\twindow.wp.components.ServerSideRender = forwardRef( ( props, ref ) => {\n\t\tdeprecated( 'wp.components.ServerSideRender', {\n\t\t\tsince: '5.3',\n\t\t\talternative: 'wp.serverSideRender',\n\t\t} );\n\t\treturn <ExportedServerSideRender { ...props } ref={ ref } />;\n\t} );\n}\n\nexport default ExportedServerSideRender;\n"]}
1
+ {"version":3,"sources":["@wordpress/server-side-render/src/index.js"],"names":["EMPTY_OBJECT","ExportedServerSideRender","select","coreEditorSelect","currentPostId","getCurrentPostId","urlQueryArgs","props","newUrlQueryArgs","post_id","window","wp","components","ServerSideRender","ref","since","alternative"],"mappings":";;;;;;;;;AAGA;;;;AACA;;AACA;;AAKA;;AAVA;AACA;AACA;;AAKA;AACA;AACA;;AAGA;AACA;AACA;AACA,MAAMA,YAAY,GAAG,EAArB;AAEA,MAAMC,wBAAwB,GAAG,sBAAcC,MAAF,IAAc;AAC1D;AACA;AACA;AACA,QAAMC,gBAAgB,GAAGD,MAAM,CAAE,aAAF,CAA/B;;AACA,MAAKC,gBAAL,EAAwB;AACvB,UAAMC,aAAa,GAAGD,gBAAgB,CAACE,gBAAjB,EAAtB,CADuB,CAEvB;AACA;AACA;AACA;;AACA,QAAKD,aAAa,IAAI,OAAOA,aAAP,KAAyB,QAA/C,EAA0D;AACzD,aAAO;AACNA,QAAAA;AADM,OAAP;AAGA;AACD;;AACD,SAAOJ,YAAP;AACA,CAlBgC,EAkB5B,QAAgE;AAAA,MAA9D;AAAEM,IAAAA,YAAY,GAAGN,YAAjB;AAA+BI,IAAAA,aAA/B;AAA8C,OAAGG;AAAjD,GAA8D;AACpE,QAAMC,eAAe,GAAG,sBAAS,MAAM;AACtC,QAAK,CAAEJ,aAAP,EAAuB;AACtB,aAAOE,YAAP;AACA;;AACD,WAAO;AACNG,MAAAA,OAAO,EAAEL,aADH;AAEN,SAAGE;AAFG,KAAP;AAIA,GARuB,EAQrB,CAAEF,aAAF,EAAiBE,YAAjB,CARqB,CAAxB;AAUA,SAAO,4BAAC,yBAAD;AAAkB,IAAA,YAAY,EAAGE;AAAjC,KAAwDD,KAAxD,EAAP;AACA,CA9BgC,CAAjC;;AAgCA,IAAKG,MAAM,IAAIA,MAAM,CAACC,EAAjB,IAAuBD,MAAM,CAACC,EAAP,CAAUC,UAAtC,EAAmD;AAClDF,EAAAA,MAAM,CAACC,EAAP,CAAUC,UAAV,CAAqBC,gBAArB,GAAwC,yBAAY,CAAEN,KAAF,EAASO,GAAT,KAAkB;AACrE,6BAAY,gCAAZ,EAA8C;AAC7CC,MAAAA,KAAK,EAAE,KADsC;AAE7CC,MAAAA,WAAW,EAAE;AAFgC,KAA9C;AAIA,WAAO,4BAAC,wBAAD,6BAA+BT,KAA/B;AAAuC,MAAA,GAAG,EAAGO;AAA7C,OAAP;AACA,GANuC,CAAxC;AAOA;;eAEcb,wB","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, forwardRef } from '@wordpress/element';\nimport { withSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport ServerSideRender from './server-side-render';\n\n/**\n * Constants\n */\nconst EMPTY_OBJECT = {};\n\nconst ExportedServerSideRender = withSelect( ( select ) => {\n\t// FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.\n\t// It is used by blocks that can be loaded into a *non-post* block editor.\n\t// eslint-disable-next-line @wordpress/data-no-store-string-literals\n\tconst coreEditorSelect = select( 'core/editor' );\n\tif ( coreEditorSelect ) {\n\t\tconst currentPostId = coreEditorSelect.getCurrentPostId();\n\t\t// For templates and template parts we use a custom ID format.\n\t\t// Since they aren't real posts, we don't want to use their ID\n\t\t// for server-side rendering. Since they use a string based ID,\n\t\t// we can assume real post IDs are numbers.\n\t\tif ( currentPostId && typeof currentPostId === 'number' ) {\n\t\t\treturn {\n\t\t\t\tcurrentPostId,\n\t\t\t};\n\t\t}\n\t}\n\treturn EMPTY_OBJECT;\n} )( ( { urlQueryArgs = EMPTY_OBJECT, currentPostId, ...props } ) => {\n\tconst newUrlQueryArgs = useMemo( () => {\n\t\tif ( ! currentPostId ) {\n\t\t\treturn urlQueryArgs;\n\t\t}\n\t\treturn {\n\t\t\tpost_id: currentPostId,\n\t\t\t...urlQueryArgs,\n\t\t};\n\t}, [ currentPostId, urlQueryArgs ] );\n\n\treturn <ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />;\n} );\n\nif ( window && window.wp && window.wp.components ) {\n\twindow.wp.components.ServerSideRender = forwardRef( ( props, ref ) => {\n\t\tdeprecated( 'wp.components.ServerSideRender', {\n\t\t\tsince: '5.3',\n\t\t\talternative: 'wp.serverSideRender',\n\t\t} );\n\t\treturn <ExportedServerSideRender { ...props } ref={ ref } />;\n\t} );\n}\n\nexport default ExportedServerSideRender;\n"]}
@@ -5,8 +5,8 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.rendererPath = rendererPath;
9
8
  exports.default = ServerSideRender;
9
+ exports.rendererPath = rendererPath;
10
10
 
11
11
  var _element = require("@wordpress/element");
12
12
 
@@ -33,7 +33,9 @@ var _blocks = require("@wordpress/blocks");
33
33
  /**
34
34
  * WordPress dependencies
35
35
  */
36
- function rendererPath(block, attributes = null, urlQueryArgs = {}) {
36
+ function rendererPath(block) {
37
+ let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
38
+ let urlQueryArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
37
39
  return (0, _url.addQueryArgs)(`/wp/v2/block-renderer/${block}`, {
38
40
  context: 'edit',
39
41
  ...(null !== attributes ? {
@@ -43,18 +45,20 @@ function rendererPath(block, attributes = null, urlQueryArgs = {}) {
43
45
  });
44
46
  }
45
47
 
46
- function DefaultEmptyResponsePlaceholder({
47
- className
48
- }) {
48
+ function DefaultEmptyResponsePlaceholder(_ref) {
49
+ let {
50
+ className
51
+ } = _ref;
49
52
  return (0, _element.createElement)(_components.Placeholder, {
50
53
  className: className
51
54
  }, (0, _i18n.__)('Block rendered as empty.'));
52
55
  }
53
56
 
54
- function DefaultErrorResponsePlaceholder({
55
- response,
56
- className
57
- }) {
57
+ function DefaultErrorResponsePlaceholder(_ref2) {
58
+ let {
59
+ response,
60
+ className
61
+ } = _ref2;
58
62
  const errorMessage = (0, _i18n.sprintf)( // translators: %s: error message describing the problem
59
63
  (0, _i18n.__)('Error loading block: %s'), response.errorMsg);
60
64
  return (0, _element.createElement)(_components.Placeholder, {
@@ -62,12 +66,28 @@ function DefaultErrorResponsePlaceholder({
62
66
  }, errorMessage);
63
67
  }
64
68
 
65
- function DefaultLoadingResponsePlaceholder({
66
- className
67
- }) {
68
- return (0, _element.createElement)(_components.Placeholder, {
69
- className: className
70
- }, (0, _element.createElement)(_components.Spinner, null));
69
+ function DefaultLoadingResponsePlaceholder(_ref3) {
70
+ let {
71
+ children,
72
+ showLoader
73
+ } = _ref3;
74
+ return (0, _element.createElement)("div", {
75
+ style: {
76
+ position: 'relative'
77
+ }
78
+ }, showLoader && (0, _element.createElement)("div", {
79
+ style: {
80
+ position: 'absolute',
81
+ top: '50%',
82
+ left: '50%',
83
+ marginTop: '-9px',
84
+ marginLeft: '-9px'
85
+ }
86
+ }, (0, _element.createElement)(_components.Spinner, null)), (0, _element.createElement)("div", {
87
+ style: {
88
+ opacity: showLoader ? '0.3' : 1
89
+ }
90
+ }, children));
71
91
  }
72
92
 
73
93
  function ServerSideRender(props) {
@@ -82,19 +102,18 @@ function ServerSideRender(props) {
82
102
  LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
83
103
  } = props;
84
104
  const isMountedRef = (0, _element.useRef)(true);
105
+ const [showLoader, setShowLoader] = (0, _element.useState)(false);
85
106
  const fetchRequestRef = (0, _element.useRef)();
86
107
  const [response, setResponse] = (0, _element.useState)(null);
87
108
  const prevProps = (0, _compose.usePrevious)(props);
109
+ const [isLoading, setIsLoading] = (0, _element.useState)(false);
88
110
 
89
111
  function fetchData() {
90
112
  if (!isMountedRef.current) {
91
113
  return;
92
114
  }
93
115
 
94
- if (null !== response) {
95
- setResponse(null);
96
- }
97
-
116
+ setIsLoading(true);
98
117
  const sanitizedAttributes = attributes && (0, _blocks.__experimentalSanitizeBlockAttributes)(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
99
118
  // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
100
119
 
@@ -121,6 +140,10 @@ function ServerSideRender(props) {
121
140
  errorMsg: error.message
122
141
  });
123
142
  }
143
+ }).finally(() => {
144
+ if (isMountedRef.current && fetchRequest === fetchRequestRef.current) {
145
+ setIsLoading(false);
146
+ }
124
147
  });
125
148
  return fetchRequest;
126
149
  }
@@ -140,17 +163,44 @@ function ServerSideRender(props) {
140
163
  debouncedFetchData();
141
164
  }
142
165
  });
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
+
172
+ (0, _element.useEffect)(() => {
173
+ if (!isLoading) {
174
+ return;
175
+ }
143
176
 
144
- if (response === '') {
177
+ const timeout = setTimeout(() => {
178
+ setShowLoader(true);
179
+ }, 1000);
180
+ return () => clearTimeout(timeout);
181
+ }, [isLoading]);
182
+ const hasResponse = !!response;
183
+ const hasEmptyResponse = response === '';
184
+ const hasError = response === null || response === void 0 ? void 0 : response.error;
185
+
186
+ if (hasEmptyResponse || !hasResponse) {
145
187
  return (0, _element.createElement)(EmptyResponsePlaceholder, props);
146
- } else if (!response) {
147
- return (0, _element.createElement)(LoadingResponsePlaceholder, props);
148
- } else if (response.error) {
188
+ }
189
+
190
+ if (hasError) {
149
191
  return (0, _element.createElement)(ErrorResponsePlaceholder, (0, _extends2.default)({
150
192
  response: response
151
193
  }, props));
152
194
  }
153
195
 
196
+ if (isLoading) {
197
+ return (0, _element.createElement)(LoadingResponsePlaceholder, (0, _extends2.default)({}, props, {
198
+ showLoader: showLoader
199
+ }), hasResponse && (0, _element.createElement)(_element.RawHTML, {
200
+ className: className
201
+ }, response));
202
+ }
203
+
154
204
  return (0, _element.createElement)(_element.RawHTML, {
155
205
  className: className
156
206
  }, 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"]}
@@ -37,11 +37,12 @@ const ExportedServerSideRender = withSelect(select => {
37
37
  }
38
38
 
39
39
  return EMPTY_OBJECT;
40
- })(({
41
- urlQueryArgs = EMPTY_OBJECT,
42
- currentPostId,
43
- ...props
44
- }) => {
40
+ })(_ref => {
41
+ let {
42
+ urlQueryArgs = EMPTY_OBJECT,
43
+ currentPostId,
44
+ ...props
45
+ } = _ref;
45
46
  const newUrlQueryArgs = useMemo(() => {
46
47
  if (!currentPostId) {
47
48
  return urlQueryArgs;
@@ -1 +1 @@
1
- {"version":3,"sources":["@wordpress/server-side-render/src/index.js"],"names":["useMemo","forwardRef","withSelect","deprecated","ServerSideRender","EMPTY_OBJECT","ExportedServerSideRender","select","coreEditorSelect","currentPostId","getCurrentPostId","urlQueryArgs","props","newUrlQueryArgs","post_id","window","wp","components","ref","since","alternative"],"mappings":";;;AAAA;AACA;AACA;AACA,SAASA,OAAT,EAAkBC,UAAlB,QAAoC,oBAApC;AACA,SAASC,UAAT,QAA2B,iBAA3B;AACA,OAAOC,UAAP,MAAuB,uBAAvB;AAEA;AACA;AACA;;AACA,OAAOC,gBAAP,MAA6B,sBAA7B;AAEA;AACA;AACA;;AACA,MAAMC,YAAY,GAAG,EAArB;AAEA,MAAMC,wBAAwB,GAAGJ,UAAU,CAAIK,MAAF,IAAc;AAC1D;AACA;AACA;AACA,QAAMC,gBAAgB,GAAGD,MAAM,CAAE,aAAF,CAA/B;;AACA,MAAKC,gBAAL,EAAwB;AACvB,UAAMC,aAAa,GAAGD,gBAAgB,CAACE,gBAAjB,EAAtB,CADuB,CAEvB;AACA;AACA;AACA;;AACA,QAAKD,aAAa,IAAI,OAAOA,aAAP,KAAyB,QAA/C,EAA0D;AACzD,aAAO;AACNA,QAAAA;AADM,OAAP;AAGA;AACD;;AACD,SAAOJ,YAAP;AACA,CAlB0C,CAAV,CAkB5B,CAAE;AAAEM,EAAAA,YAAY,GAAGN,YAAjB;AAA+BI,EAAAA,aAA/B;AAA8C,KAAGG;AAAjD,CAAF,KAAgE;AACpE,QAAMC,eAAe,GAAGb,OAAO,CAAE,MAAM;AACtC,QAAK,CAAES,aAAP,EAAuB;AACtB,aAAOE,YAAP;AACA;;AACD,WAAO;AACNG,MAAAA,OAAO,EAAEL,aADH;AAEN,SAAGE;AAFG,KAAP;AAIA,GAR8B,EAQ5B,CAAEF,aAAF,EAAiBE,YAAjB,CAR4B,CAA/B;AAUA,SAAO,cAAC,gBAAD;AAAkB,IAAA,YAAY,EAAGE;AAAjC,KAAwDD,KAAxD,EAAP;AACA,CA9BgC,CAAjC;;AAgCA,IAAKG,MAAM,IAAIA,MAAM,CAACC,EAAjB,IAAuBD,MAAM,CAACC,EAAP,CAAUC,UAAtC,EAAmD;AAClDF,EAAAA,MAAM,CAACC,EAAP,CAAUC,UAAV,CAAqBb,gBAArB,GAAwCH,UAAU,CAAE,CAAEW,KAAF,EAASM,GAAT,KAAkB;AACrEf,IAAAA,UAAU,CAAE,gCAAF,EAAoC;AAC7CgB,MAAAA,KAAK,EAAE,KADsC;AAE7CC,MAAAA,WAAW,EAAE;AAFgC,KAApC,CAAV;AAIA,WAAO,cAAC,wBAAD,eAA+BR,KAA/B;AAAuC,MAAA,GAAG,EAAGM;AAA7C,OAAP;AACA,GANiD,CAAlD;AAOA;;AAED,eAAeZ,wBAAf","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, forwardRef } from '@wordpress/element';\nimport { withSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport ServerSideRender from './server-side-render';\n\n/**\n * Constants\n */\nconst EMPTY_OBJECT = {};\n\nconst ExportedServerSideRender = withSelect( ( select ) => {\n\t// FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.\n\t// It is used by blocks that can be loaded into a *non-post* block editor.\n\t// eslint-disable-next-line @wordpress/data-no-store-string-literals\n\tconst coreEditorSelect = select( 'core/editor' );\n\tif ( coreEditorSelect ) {\n\t\tconst currentPostId = coreEditorSelect.getCurrentPostId();\n\t\t// For templates and template parts we use a custom ID format.\n\t\t// Since they aren't real posts, we don't want to use their ID\n\t\t// for server-side rendering. Since they use a string based ID,\n\t\t// we can assume real post IDs are numbers.\n\t\tif ( currentPostId && typeof currentPostId === 'number' ) {\n\t\t\treturn {\n\t\t\t\tcurrentPostId,\n\t\t\t};\n\t\t}\n\t}\n\treturn EMPTY_OBJECT;\n} )( ( { urlQueryArgs = EMPTY_OBJECT, currentPostId, ...props } ) => {\n\tconst newUrlQueryArgs = useMemo( () => {\n\t\tif ( ! currentPostId ) {\n\t\t\treturn urlQueryArgs;\n\t\t}\n\t\treturn {\n\t\t\tpost_id: currentPostId,\n\t\t\t...urlQueryArgs,\n\t\t};\n\t}, [ currentPostId, urlQueryArgs ] );\n\n\treturn <ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />;\n} );\n\nif ( window && window.wp && window.wp.components ) {\n\twindow.wp.components.ServerSideRender = forwardRef( ( props, ref ) => {\n\t\tdeprecated( 'wp.components.ServerSideRender', {\n\t\t\tsince: '5.3',\n\t\t\talternative: 'wp.serverSideRender',\n\t\t} );\n\t\treturn <ExportedServerSideRender { ...props } ref={ ref } />;\n\t} );\n}\n\nexport default ExportedServerSideRender;\n"]}
1
+ {"version":3,"sources":["@wordpress/server-side-render/src/index.js"],"names":["useMemo","forwardRef","withSelect","deprecated","ServerSideRender","EMPTY_OBJECT","ExportedServerSideRender","select","coreEditorSelect","currentPostId","getCurrentPostId","urlQueryArgs","props","newUrlQueryArgs","post_id","window","wp","components","ref","since","alternative"],"mappings":";;;AAAA;AACA;AACA;AACA,SAASA,OAAT,EAAkBC,UAAlB,QAAoC,oBAApC;AACA,SAASC,UAAT,QAA2B,iBAA3B;AACA,OAAOC,UAAP,MAAuB,uBAAvB;AAEA;AACA;AACA;;AACA,OAAOC,gBAAP,MAA6B,sBAA7B;AAEA;AACA;AACA;;AACA,MAAMC,YAAY,GAAG,EAArB;AAEA,MAAMC,wBAAwB,GAAGJ,UAAU,CAAIK,MAAF,IAAc;AAC1D;AACA;AACA;AACA,QAAMC,gBAAgB,GAAGD,MAAM,CAAE,aAAF,CAA/B;;AACA,MAAKC,gBAAL,EAAwB;AACvB,UAAMC,aAAa,GAAGD,gBAAgB,CAACE,gBAAjB,EAAtB,CADuB,CAEvB;AACA;AACA;AACA;;AACA,QAAKD,aAAa,IAAI,OAAOA,aAAP,KAAyB,QAA/C,EAA0D;AACzD,aAAO;AACNA,QAAAA;AADM,OAAP;AAGA;AACD;;AACD,SAAOJ,YAAP;AACA,CAlB0C,CAAV,CAkB5B,QAAgE;AAAA,MAA9D;AAAEM,IAAAA,YAAY,GAAGN,YAAjB;AAA+BI,IAAAA,aAA/B;AAA8C,OAAGG;AAAjD,GAA8D;AACpE,QAAMC,eAAe,GAAGb,OAAO,CAAE,MAAM;AACtC,QAAK,CAAES,aAAP,EAAuB;AACtB,aAAOE,YAAP;AACA;;AACD,WAAO;AACNG,MAAAA,OAAO,EAAEL,aADH;AAEN,SAAGE;AAFG,KAAP;AAIA,GAR8B,EAQ5B,CAAEF,aAAF,EAAiBE,YAAjB,CAR4B,CAA/B;AAUA,SAAO,cAAC,gBAAD;AAAkB,IAAA,YAAY,EAAGE;AAAjC,KAAwDD,KAAxD,EAAP;AACA,CA9BgC,CAAjC;;AAgCA,IAAKG,MAAM,IAAIA,MAAM,CAACC,EAAjB,IAAuBD,MAAM,CAACC,EAAP,CAAUC,UAAtC,EAAmD;AAClDF,EAAAA,MAAM,CAACC,EAAP,CAAUC,UAAV,CAAqBb,gBAArB,GAAwCH,UAAU,CAAE,CAAEW,KAAF,EAASM,GAAT,KAAkB;AACrEf,IAAAA,UAAU,CAAE,gCAAF,EAAoC;AAC7CgB,MAAAA,KAAK,EAAE,KADsC;AAE7CC,MAAAA,WAAW,EAAE;AAFgC,KAApC,CAAV;AAIA,WAAO,cAAC,wBAAD,eAA+BR,KAA/B;AAAuC,MAAA,GAAG,EAAGM;AAA7C,OAAP;AACA,GANiD,CAAlD;AAOA;;AAED,eAAeZ,wBAAf","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo, forwardRef } from '@wordpress/element';\nimport { withSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Internal dependencies\n */\nimport ServerSideRender from './server-side-render';\n\n/**\n * Constants\n */\nconst EMPTY_OBJECT = {};\n\nconst ExportedServerSideRender = withSelect( ( select ) => {\n\t// FIXME: @wordpress/server-side-render should not depend on @wordpress/editor.\n\t// It is used by blocks that can be loaded into a *non-post* block editor.\n\t// eslint-disable-next-line @wordpress/data-no-store-string-literals\n\tconst coreEditorSelect = select( 'core/editor' );\n\tif ( coreEditorSelect ) {\n\t\tconst currentPostId = coreEditorSelect.getCurrentPostId();\n\t\t// For templates and template parts we use a custom ID format.\n\t\t// Since they aren't real posts, we don't want to use their ID\n\t\t// for server-side rendering. Since they use a string based ID,\n\t\t// we can assume real post IDs are numbers.\n\t\tif ( currentPostId && typeof currentPostId === 'number' ) {\n\t\t\treturn {\n\t\t\t\tcurrentPostId,\n\t\t\t};\n\t\t}\n\t}\n\treturn EMPTY_OBJECT;\n} )( ( { urlQueryArgs = EMPTY_OBJECT, currentPostId, ...props } ) => {\n\tconst newUrlQueryArgs = useMemo( () => {\n\t\tif ( ! currentPostId ) {\n\t\t\treturn urlQueryArgs;\n\t\t}\n\t\treturn {\n\t\t\tpost_id: currentPostId,\n\t\t\t...urlQueryArgs,\n\t\t};\n\t}, [ currentPostId, urlQueryArgs ] );\n\n\treturn <ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />;\n} );\n\nif ( window && window.wp && window.wp.components ) {\n\twindow.wp.components.ServerSideRender = forwardRef( ( props, ref ) => {\n\t\tdeprecated( 'wp.components.ServerSideRender', {\n\t\t\tsince: '5.3',\n\t\t\talternative: 'wp.serverSideRender',\n\t\t} );\n\t\treturn <ExportedServerSideRender { ...props } ref={ ref } />;\n\t} );\n}\n\nexport default ExportedServerSideRender;\n"]}
@@ -16,7 +16,9 @@ import apiFetch from '@wordpress/api-fetch';
16
16
  import { addQueryArgs } from '@wordpress/url';
17
17
  import { Placeholder, Spinner } from '@wordpress/components';
18
18
  import { __experimentalSanitizeBlockAttributes } from '@wordpress/blocks';
19
- export function rendererPath(block, attributes = null, urlQueryArgs = {}) {
19
+ export function rendererPath(block) {
20
+ let attributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
21
+ let urlQueryArgs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
20
22
  return addQueryArgs(`/wp/v2/block-renderer/${block}`, {
21
23
  context: 'edit',
22
24
  ...(null !== attributes ? {
@@ -26,18 +28,20 @@ export function rendererPath(block, attributes = null, urlQueryArgs = {}) {
26
28
  });
27
29
  }
28
30
 
29
- function DefaultEmptyResponsePlaceholder({
30
- className
31
- }) {
31
+ function DefaultEmptyResponsePlaceholder(_ref) {
32
+ let {
33
+ className
34
+ } = _ref;
32
35
  return createElement(Placeholder, {
33
36
  className: className
34
37
  }, __('Block rendered as empty.'));
35
38
  }
36
39
 
37
- function DefaultErrorResponsePlaceholder({
38
- response,
39
- className
40
- }) {
40
+ function DefaultErrorResponsePlaceholder(_ref2) {
41
+ let {
42
+ response,
43
+ className
44
+ } = _ref2;
41
45
  const errorMessage = sprintf( // translators: %s: error message describing the problem
42
46
  __('Error loading block: %s'), response.errorMsg);
43
47
  return createElement(Placeholder, {
@@ -45,12 +49,28 @@ function DefaultErrorResponsePlaceholder({
45
49
  }, errorMessage);
46
50
  }
47
51
 
48
- function DefaultLoadingResponsePlaceholder({
49
- className
50
- }) {
51
- return createElement(Placeholder, {
52
- className: className
53
- }, createElement(Spinner, null));
52
+ function DefaultLoadingResponsePlaceholder(_ref3) {
53
+ let {
54
+ children,
55
+ showLoader
56
+ } = _ref3;
57
+ return createElement("div", {
58
+ style: {
59
+ position: 'relative'
60
+ }
61
+ }, showLoader && createElement("div", {
62
+ style: {
63
+ position: 'absolute',
64
+ top: '50%',
65
+ left: '50%',
66
+ marginTop: '-9px',
67
+ marginLeft: '-9px'
68
+ }
69
+ }, createElement(Spinner, null)), createElement("div", {
70
+ style: {
71
+ opacity: showLoader ? '0.3' : 1
72
+ }
73
+ }, children));
54
74
  }
55
75
 
56
76
  export default function ServerSideRender(props) {
@@ -65,18 +85,18 @@ export default function ServerSideRender(props) {
65
85
  LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder
66
86
  } = props;
67
87
  const isMountedRef = useRef(true);
88
+ const [showLoader, setShowLoader] = useState(false);
68
89
  const fetchRequestRef = useRef();
69
90
  const [response, setResponse] = useState(null);
70
91
  const prevProps = usePrevious(props);
92
+ const [isLoading, setIsLoading] = useState(false);
71
93
 
72
94
  function fetchData() {
73
95
  if (!isMountedRef.current) {
74
96
  return;
75
97
  }
76
98
 
77
- if (null !== response) {
78
- setResponse(null);
79
- }
99
+ setIsLoading(true);
80
100
 
81
101
  const sanitizedAttributes = attributes && __experimentalSanitizeBlockAttributes(block, attributes); // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
82
102
  // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
@@ -105,6 +125,10 @@ export default function ServerSideRender(props) {
105
125
  errorMsg: error.message
106
126
  });
107
127
  }
128
+ }).finally(() => {
129
+ if (isMountedRef.current && fetchRequest === fetchRequestRef.current) {
130
+ setIsLoading(false);
131
+ }
108
132
  });
109
133
  return fetchRequest;
110
134
  }
@@ -124,17 +148,44 @@ export default function ServerSideRender(props) {
124
148
  debouncedFetchData();
125
149
  }
126
150
  });
151
+ /**
152
+ * Effect to handle showing the loading placeholder.
153
+ * Show it only if there is no previous response or
154
+ * the request takes more than one second.
155
+ */
127
156
 
128
- if (response === '') {
157
+ useEffect(() => {
158
+ if (!isLoading) {
159
+ return;
160
+ }
161
+
162
+ const timeout = setTimeout(() => {
163
+ setShowLoader(true);
164
+ }, 1000);
165
+ return () => clearTimeout(timeout);
166
+ }, [isLoading]);
167
+ const hasResponse = !!response;
168
+ const hasEmptyResponse = response === '';
169
+ const hasError = response === null || response === void 0 ? void 0 : response.error;
170
+
171
+ if (hasEmptyResponse || !hasResponse) {
129
172
  return createElement(EmptyResponsePlaceholder, props);
130
- } else if (!response) {
131
- return createElement(LoadingResponsePlaceholder, props);
132
- } else if (response.error) {
173
+ }
174
+
175
+ if (hasError) {
133
176
  return createElement(ErrorResponsePlaceholder, _extends({
134
177
  response: response
135
178
  }, props));
136
179
  }
137
180
 
181
+ if (isLoading) {
182
+ return createElement(LoadingResponsePlaceholder, _extends({}, props, {
183
+ showLoader: showLoader
184
+ }), hasResponse && createElement(RawHTML, {
185
+ className: className
186
+ }, response));
187
+ }
188
+
138
189
  return createElement(RawHTML, {
139
190
  className: className
140
191
  }, 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.2",
3
+ "version": "3.0.6",
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",
@@ -26,20 +26,20 @@
26
26
  "module": "build-module/index.js",
27
27
  "react-native": "src/index",
28
28
  "dependencies": {
29
- "@babel/runtime": "^7.13.10",
30
- "@wordpress/api-fetch": "^5.2.2",
31
- "@wordpress/blocks": "^11.1.0",
32
- "@wordpress/components": "^17.0.0",
33
- "@wordpress/compose": "^5.0.2",
34
- "@wordpress/data": "^6.1.0",
35
- "@wordpress/deprecated": "^3.2.1",
36
- "@wordpress/element": "^4.0.1",
37
- "@wordpress/i18n": "^4.2.2",
38
- "@wordpress/url": "^3.2.2",
29
+ "@babel/runtime": "^7.16.0",
30
+ "@wordpress/api-fetch": "^5.2.6",
31
+ "@wordpress/blocks": "^11.1.4",
32
+ "@wordpress/components": "^19.0.2",
33
+ "@wordpress/compose": "^5.0.6",
34
+ "@wordpress/data": "^6.1.4",
35
+ "@wordpress/deprecated": "^3.2.3",
36
+ "@wordpress/element": "^4.0.4",
37
+ "@wordpress/i18n": "^4.2.4",
38
+ "@wordpress/url": "^3.3.1",
39
39
  "lodash": "^4.17.21"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public"
43
43
  },
44
- "gitHead": "98c42a7187f788fe3e023f04df7f5dcbdae4e4e7"
44
+ "gitHead": "9a1dd3474d937468e4cf9caf9886ad61ef0a8f50"
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( { className } ) {
42
+ function DefaultLoadingResponsePlaceholder( { children, showLoader } ) {
43
43
  return (
44
- <Placeholder className={ className }>
45
- <Spinner />
46
- </Placeholder>
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
- if ( null !== response ) {
72
- setResponse( null );
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
- if ( response === '' ) {
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
- } else if ( ! response ) {
145
- return <LoadingResponsePlaceholder { ...props } />;
146
- } else if ( response.error ) {
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
  }