react-instantsearch icon indicating copy to clipboard operation
react-instantsearch copied to clipboard

WARNING - Detected multiple renderers concurrently rendering the same context provider (React 18.0.0?)

Open VegtMedia-Alex opened this issue 3 years ago • 17 comments

🐛 Bug description

I get the following warning on the server side in react when i use:

import { findResultsState } from 'react-instantsearch-dom/server';

Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported. at Index (node_modules/react-instantsearch-core/dist/cjs/widgets/Index.js:86:34) at IndexWrapper (node_modules/react-instantsearch-core/dist/cjs/widgets/Index.js:157:31)

Modules in package.json:

"react": "^18.0.0", "react-dom": "^18.0.0", "algoliasearch": "^4.13.0", "react-instantsearch-dom": "^6.23.3",

VegtMedia-Alex avatar Apr 20 '22 20:04 VegtMedia-Alex

Can you please reproduce the behavior in this React InstantSearch Server sandbox?

francoischalifour avatar Apr 21 '22 07:04 francoischalifour

That would be very much work...

VegtMedia-Alex avatar Apr 21 '22 14:04 VegtMedia-Alex

Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
    at InstantSearch (/node_modules/react-instantsearch-core/dist/cjs/widgets/InstantSearch.js:101:34)
    at MainIndex (webpack-internal:///(api)/./src/components/organisms/MainIndex/MainIndex.js:18:22)
    at ServerSearchResults (webpack-internal:///(api)/./src/components/molecules/ServerSearchResults/ServerSearchResults.js:21:32)
Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.
    at Index (/node_modules/react-instantsearch-core/dist/cjs/widgets/Index.js:86:34)
    at IndexWrapper (/node_modules/react-instantsearch-core/dist/cjs/widgets/Index.js:157:31)
    at Index (webpack-internal:///(api)/./src/components/organisms/Index/index.js:21:18)
    at InstantSearch (/node_modules/react-instantsearch-core/dist/cjs/widgets/InstantSearch.js:101:34)
    at MainIndex (webpack-internal:///(api)/./src/components/organisms/MainIndex/MainIndex.js:18:22)
    at ServerSearchResults (webpack-internal:///(api)/./src/components/molecules/ServerSearchResults/ServerSearchResults.js:21:32)

VegtMedia-Alex avatar Apr 21 '22 14:04 VegtMedia-Alex

We can't help you further without any snippets or reproduction. The sandbox I sent you uses React 18 and doesn't have this problem, so this likely comes from your application code.

francoischalifour avatar Apr 21 '22 14:04 francoischalifour

Do you have the structure of your InstantSearch application and the part which calls findResultsState at least? I'm wondering if this is because of a reused context provider that would not happen if only the InstantSearch app is passed to findResultsState

Haroenv avatar Apr 21 '22 14:04 Haroenv

Sure, here is the algolia utility:

import algoliasearch from 'algoliasearch/lite';
import { asyncForEach } from 'helpers/core';
import { getIndexName } from 'helpers/search';
import { findResultsState as instantSearchFindResultsState } from 'react-instantsearch-dom/server';
import { logger } from 'utils/logging';

export const searchClient = algoliasearch(
	process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
	process.env.NEXT_PUBLIC_ALGOLIA_API_KEY,
);

export const findResultsState = async(Component, {
	indexName,
	indexes,
	...props
}) => {
	let resultsState = {};

	try {
		let indexesExist = true;

		await asyncForEach([
			indexName,
			...new Set(indexes),
		], async(searchIndex) => {
			searchIndex = getIndexName({
				indexName: searchIndex,
			});

			if (
				!await searchClient.initIndex(searchIndex).exists()
			) {
				indexesExist = searchIndex;
			}
		});

		if (indexesExist === true) {
			indexName = getIndexName({
				indexName,
			});

			resultsState = await instantSearchFindResultsState(Component, {
				searchClient,
				indexName,
				indexes,
				...props,
			});
		} else {
			logger.warning(`utils/algolia - findResultsState() - Index: ${indexesExist} does not exist`);
		}
	} catch (error) {
		logger.error('utils/algolia - findResultsState() - Error', {
			error,
			indexName,
			props,
		});
	}

	return JSON.parse(JSON.stringify(resultsState));
};

The "Component" getting passed is ServerSearchResults.js

import Index from 'components/organisms/Index';
import MainIndex from 'components/organisms/MainIndex';
import React from 'react';
import { Hits } from 'react-instantsearch-dom';

const ServerSearchResults = ({
	mainIndex,
	indexName,
	indexes,
	preset,
	hitsPerPage = 24,
	...props
}) => {
	if (indexName) {
		if (!mainIndex) {
			mainIndex = indexName;
		}

		if (!indexes) {
			indexes = [indexName];
		}
	}

	if (!indexes || indexes.length === 0) {
		return null;
	}

	return (
		<MainIndex mainIndex={mainIndex} {...props}>
			{indexes.map((indexName, index) => (
				<Index
					key={`${indexName}-${index}`}
					indexName={indexName}
					preset={preset}
					hitsPerPage={hitsPerPage}
				>
					<Hits
						hitComponent={({ hit }) => (
							<React.Fragment>
								{hit.brand} - {hit.name}
							</React.Fragment>
						)}
					/>
				</Index>
			))}
		</MainIndex>
	);
};

export default ServerSearchResults;

VegtMedia-Alex avatar Apr 21 '22 14:04 VegtMedia-Alex

what is in the MainIndex component @DB-Alex ?

Haroenv avatar Apr 21 '22 14:04 Haroenv

MainIndex component:

import { getIndexName } from 'helpers/search';
import { useInstantSearch } from 'providers/InstantSearchProvider';
import React from 'react';
import { InstantSearch } from 'react-instantsearch-dom';

const MainIndex = ({
	mainIndex,
	children,
	...props
}) => {
	let {
		searchClient,
		resultsState,
		handleSearchStateChange,
		searchState,
	} = useInstantSearch();

	return (
		<InstantSearch
			indexName={getIndexName({
				indexName: mainIndex,
			})}
			searchClient={searchClient}
			resultsState={resultsState}
			onSearchStateChange={handleSearchStateChange}
			searchState={searchState}
			{...props}
		>
			{children}
		</InstantSearch>
	);
};

export default MainIndex;

VegtMedia-Alex avatar Apr 21 '22 14:04 VegtMedia-Alex

I've managed to reproduce this now with just InstantSearch, but as far as I can tell it has no adverse effects. I wonder how eg. Apollo with a very similar design avoids this warning

Haroenv avatar May 02 '22 08:05 Haroenv

Any update on this? We are seeing the same issue in our React/Next app after upgrading to React 18.0.0

Some additional info that we found while researching this error: https://github.com/reactwg/react-18/discussions/19 https://github.com/reactwg/react-18/discussions/17 https://github.com/reactwg/react-18/discussions/18

It may not be causing issues now but from the React blog: https://reactjs.org/blog/2022/03/29/react-v18.html#new-strict-mode-behaviors it looks like it may cause breaking changes in the future.

MrSnufalafogus avatar May 06 '22 17:05 MrSnufalafogus

Not yet, sorry! I'm not fully sure whet the underlying cause is, which components are shared since as far as I can tell it's a completely separate "app" tree being created, so I'm not sure which part is the same provider (InstantSearch itself?).

I did find since that Apollo for example avoids this by returning the result of renderToString and asking the user to render that in a simple html wrapper after.

If you have any ideas on what could be the underlying reasons or solution, I'm all ears!

Relevant issues:

  • https://github.com/facebook/react/issues/13177
  • https://github.com/facebook/react/issues/19519
  • https://github.com/facebook/react/issues/22796

Haroenv avatar May 09 '22 14:05 Haroenv

We also have the same issue after the upgrade. The culprit for us seems to be the getServerState from react-instantsearch-hooks-server

wenche avatar May 25 '22 09:05 wenche

As far as I can tell, this is an incorrect warning from React (https://github.com/facebook/react/issues/22796) and it has no effect apart from giving that warning. Conceptually I haven't found a way to avoid the error except by manually ignoring it

Haroenv avatar May 30 '22 08:05 Haroenv

This issue is reproducible on https://github.com/algolia/pwa-ecom-ui-template after you upgrade React to v18. Could you please check?

Qwal avatar Jun 20 '22 15:06 Qwal

Hey @Qwal, we are aware of this warning, but it doesn't have an impact on the application, but is a result of React counting two distinct renders that happen subsequently as if they happen concurrently (not the case). You can follow in the react issue linked earlier: https://github.com/facebook/react/issues/22796

Haroenv avatar Jun 21 '22 07:06 Haroenv

Hi @Haroenv this is what I see after running the app: image

It has impact on application ex. SEO & Performance will be downgraded if we do not match the SSR state with CSR state.

We are building POC around Algolia to validate if we can use it for new shop we are building and this is a first obstacle.

If I understand correctly the issue you linked is related to unit testing.

Qwal avatar Jun 21 '22 09:06 Qwal

Ah, what you're showing isn't the same issue as this one originally was about. The state not matching between client and server would indeed be an issue.

When I update the default next example to react 18 it works as expected (https://codesandbox.io/s/admiring-benji-ovjzlk?file=/pages/index.js) so I'm guessing the client mismatch is something due to a specific implementation in the pwa ecom ui template, and thus an issue should be opened there (cc @FabienMotte). I'm not sure yet what the specific issue could be though

The react issue shows up in unit testing, but also in our case of server side rendering with an unneeded warning.

Haroenv avatar Jun 21 '22 11:06 Haroenv

@Haroenv for me, the only issue with this is, it gets stuck in a repeating loop. I have tried to work out how to break out of it but I can't. Which then leads to this error: https://stackoverflow.com/questions/55763428/react-native-error-enospc-system-limit-for-number-of-file-watchers-reached so I'll need to reset my machine after a little while.

176 after a few seconds :O image

hutber avatar Sep 25 '22 22:09 hutber

@hutber could you open a new issue with reproduction, it seems unrelated

Haroenv avatar Sep 26 '22 11:09 Haroenv