Open bturner1273 opened 1 year ago
Hi @bturner1273, I've just taken the example from the website and updated to React 18 and it seems to be working (see CodeSandbox).
Are you able to reproduce the issue so we can look into it further?
Here's a slightly bigger reproduction. This is simply an app that converts tweets to images, but it isn't working correctly in v18. However, it is working correctly in the development environment, and this is what happens when I deploy it. For your reference.
An error occurred in development env:
Warning: Prop `id` did not match. Server: "react-select-6-live-region" Client: "react-select-2-live-region"
at span
at http://localhost:3000/build/routes/index-WS3DWJYT.js:2726:28
at A11yText2
at LiveRegion2 (http://localhost:3000/build/routes/index-WS3DWJYT.js:6911:29)
at div
at http://localhost:3000/build/routes/index-WS3DWJYT.js:2726:28
at SelectContainer2 (http://localhost:3000/build/routes/index-WS3DWJYT.js:6251:24)
at Select2 (http://localhost:3000/build/routes/index-WS3DWJYT.js:7804:5)
...
app: https://tweet2image-6b8636qux-anzu.vercel.app/ code: https://github.com/ci7lus/tweet2image/tree/repro/react-select-broken-on-18/app/components/Form
Hi @ci7lus, it's a bit hard to tell from that example if it's an issue with React 18, or an issue with Remix. I know there is a bit of extra work involved with getting Remix to play nicely with Emotion (which React Select uses for styling). This PR might be worth taking a look at: https://github.com/remix-run/examples/pull/35 Hope that helps.
I'm getting the same Prop id did not match
hydration error using Next.js 13's new appDir
with react-select
being used in a client component.
If I add a unique instanceId
to the Select
props, the hydration errors appear to go away (testing in dev right now).
Hi, I had the same problem with next (13.2.1) and I found a workaround:
const MySelect = ({
placeholder,
options,
}: ProjectEditionSelectProps) => {
const id = Date.now().toString();
const [isMounted, setIsMounted] = useState(false);
// Must be deleted once
// https://github.com/JedWatson/react-select/issues/5459 is fixed.
useEffect(() => setIsMounted(true), []);
return isMounted ? (
<Select
id={id}
options={options}
placeholder={placeholder}
className="project-edition-select-container"
classNamePrefix="project-edition-select"
/>
) : null;
};
export default MySelect;
My workaround is to display the <Select />
component only in client side. UseEffect() is only triggered client-side so the isMounted
is always false
on server side.
If you use the experimental version of Next 13, you may use use-client directive.
I'm not particularly happy with this "fix" but it leaves my console in peace.
Having the same issue with Next 13
Same issue with NextJS 13.4!
Fix it, by adding interface :
'use client'
interface ISelectProps {
data: boolean;
isDisabled: boolean;
isFocused: boolean;
isSelected: boolean;
id?: number;
}
Then make props look like this:
option: (styles: any, props: ISelectProps) => { ...
Finally put it in Select from react-select...
<Select
instanceId={useId()}
{...elseProps}
/>
Hi, I had the same problem with next (13.2.1) and I found a workaround:
const MySelect = ({ placeholder, options, }: ProjectEditionSelectProps) => { const id = Date.now().toString(); const [isMounted, setIsMounted] = useState(false); // Must be deleted once // https://github.com/JedWatson/react-select/issues/5459 is fixed. useEffect(() => setIsMounted(true), []); return isMounted ? ( <Select id={id} options={options} placeholder={placeholder} className="project-edition-select-container" classNamePrefix="project-edition-select" /> ) : null; }; export default MySelect;
My workaround is to display the
<Select />
component only in client side. UseEffect() is only triggered client-side so theisMounted
is alwaysfalse
on server side.If you use the experimental version of Next 13, you may use use-client directive.
I'm not particularly happy with this "fix" but it leaves my console in peace.
Hey thanks for the solution. This works as the Component renders once in the client side.
In my case, i solved using
const AsyncSelect = dynamic(() => import("react-select/async"), { ssr: false });
Same issue on my side as well. Not sure why this happens. IMHO does not make sense.
Same problem over here...
Same problem
Hi, I had the same problem with next (13.2.1) and I found a workaround:
const MySelect = ({ placeholder, options, }: ProjectEditionSelectProps) => { const id = Date.now().toString(); const [isMounted, setIsMounted] = useState(false); // Must be deleted once // https://github.com/JedWatson/react-select/issues/5459 is fixed. useEffect(() => setIsMounted(true), []); return isMounted ? ( <Select id={id} options={options} placeholder={placeholder} className="project-edition-select-container" classNamePrefix="project-edition-select" /> ) : null; }; export default MySelect;
My workaround is to display the
<Select />
component only in client side. UseEffect() is only triggered client-side so theisMounted
is alwaysfalse
on server side.If you use the experimental version of Next 13, you may use use-client directive.
I'm not particularly happy with this "fix" but it leaves my console in peace.
Thanks for the solution, it is work for me, too but can u explain to me that what exactly u did here? I'm using "use server" also in the page. why we are check the ssr
"I donβt know if anyone is still having the same problem. I found something that fixes the message console issue
<Select instanceId={'wsad123wqwe'} />
For Nextjs import with next dynamic. It worked for me
import dynamic from 'next/dynamic' const CreatableSelect = dynamic(() => import('react-select/creatable'), { loading: () =>
Loading...
, })For the Nextjs 14 with Pages Router this is the fix
import dynamic from "next/dynamic"; const Select = dynamic(() => import("react-select"), { ssr: false });
It'll render the Select Component on the client side.
"next": "^14.0.4", // app router
"react-select": "^5.8.0",
same error here, but I got another error
I use dynamic import and instanceId and useEffect way to prevent error and it's work, but when I put MySelect component into another component like
export function MyForm (){
return <form>
<MySelect />
</form>
}
the error show again, seems like I have to use dynamic import on top level import my MyForm component, after dynamic import, error will gone
const MyForm = dynamic(()=>import('./myForm'), {ssr: false})
export function Page (){
return <>
<MySelect /> // this one not show error
<MyForm /> // this one show error if I don't use dynamic import MyForm
</>
}
I think this not make sense, if I have heavy nesting component, I have to use dynamic import everywhere.
@WinnieS0728 you can add Input property in components and make aria-activedescendant undefined or whatever you like it. like below:
<Select
components={{
Input: (props) => (
<components.Input {...props} aria-activedescendant={undefined} />
),
}}
/>
@everythinginjs wow it's working. thank you so much. I forgot I can customize my own component.
before this I even create a fake select component to prevent the flash before isClient useEffect work lol. and I think useClient is better than dynamic import, because can have same props with the real component like className and placeholder. now I remove useClient useEffect and everything is working fine. maybe this is the best answer in my project.
here I share my code to anyone use nextJS and have server issue
now code
export function ReactSelect({ className, name, ...props }: Parameters<Select>[0]) {
return (
<>
<Select
{...props}
instanceId={`react-select-${props.name}`}
className={cn("w-full", className)}
closeMenuOnSelect={props.isMulti ? false : true}
menuPlacement="auto"
components={{
Input: (props) => (
<components.Input {...props} aria-activedescendant={undefined} />
),
}}
/>
</>
);
}
origin code ( with fake component and useClient hook ) * not the best answer
function FakeReactSelect({
placeholder = "Select...",
...props
}: Parameters<Select>[0] | Parameters<AsyncSelect>[0]) {
return (
<>
<div
className={cn(
"flex h-[38px] w-full rounded-[4px] border-[1px] border-[#cccccc] bg-white",
props.className,
)}
>
<p className="flex w-full items-center overflow-x-clip px-[10px] py-[2px] text-[#808080]">
{placeholder}
</p>
<div className="my-2 w-[1px] bg-[#cccccc]"></div>
<div className="flex aspect-square items-center justify-center p-2">
<svg viewBox="0 0 20 20" aria-hidden="true" focusable="false">
<path
fill="#cccccc"
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"
></path>
</svg>
</div>
</div>
</>
);
}
function useClient() {
const [isClient, setClient] = useState
export function ReactSelect(props: Parameters
return (
<>
{isClient ? (
<Select
{...props}
instanceId={react-select-${props.name}
}
className={cn("w-full", props.className)}
closeMenuOnSelect={props.isMulti ? false : true}
menuPlacement="auto"
/>
) : (
<FakeReactSelect {...props} />
)}
</>
);
}
For the Nextjs 14 with Pages Router this is the fix
import dynamic from "next/dynamic"; const Select = dynamic(() => import("react-select"), { ssr: false });
It'll render the Select Component on the client side.
This worked for me in the app router with "use client";
as well
This is so bad that I have to wait for render to see the input when doing
import dynamic from "next/dynamic"; const Select = dynamic(() => import("react-select"), { ssr: false });
Really, there is still no proper fix for this ?
I have same issue. +1
Thank you @WinnieS0728
I have same issue. +1
Just add the instanceId prop to the Select component.
You can achieve this by using the useId hook provided by React or you can just input a random id yourself.
import { useId } from 'react';
<Select
{...props}
instanceId={useId()}
/>
app-index.js:33 Warning: Prop className
did not match. Server: "__className_aaf875 vsc-initialized" Client: "__className_aaf875"
Warning: Prop
id
did not match. Server: "react-select-6-live-region" Client: "react-select-2-live-region"
Works for app folder as well, thanks!
Warning: Prop
id
did not match. Server: "react-select-6-live-region" Client: "react-select-2-live-region"Works for app folder as well, thanks!
Sorry! How worked for you? How can i remove that warning.
I ran into the same issue; my solution was a combination of using dynamic ssr false and combining the idea of a fake select on loading, as suggested by @WinnieS0728.
const Select = dynamic(() => import('react-select/async'), {
ssr: false,
loading: () => <FakeReactSelect placeholder="Select..." />,
});
function FakeReactSelect({
placeholder = 'Select Job Roles...',
className,
}: {
placeholder: string;
className?: string;
}) {
return (
<>
<div
className={cn(
'flex h-[38px] w-full rounded-[4px] border-[1px] border-[#cccccc] bg-white text-sm',
className
)}>
<p className="flex w-full items-center overflow-x-clip px-[10px] py-[2px] text-[#808080]">
{placeholder}
</p>
<div className="my-2 w-[1px] bg-[#cccccc]"></div>
<div className="flex aspect-square items-center justify-center p-2">
<svg viewBox="0 0 20 20" aria-hidden="true" focusable="false">
<path
fill="#cccccc"
d="M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"></path>
</svg>
</div>
</div>
</>
);
}
this renders a fake select while the original select loads on client, giving an illusion of responsiveness.
app-index.js:33 Warning: Prop
className
did not match. Server: "__className_aaf875 vsc-initialized" Client: "__className_aaf875"
are u fix that ??
app-index.js:33 Warning: Prop
className
did not match. Server: "__className_aaf875 vsc-initialized" Client: "__className_aaf875"are u fix that ??
No
for anyone using Next.JS, we did this:
const ValueContainer = dynamic(
() => import("react-select").then((mod) => mod.components.ValueContainer),
{
ssr: process.env.NODE_ENV === "production",
},
);
return (
<ReactSelect
...
components={{
ValueContainer: (props) => (
<ValueContainer {...props} aria-activedescendant={undefined} />
),
}}
...
/>
)
Client side render the ValueContainer component on development to get rid of the warning / error
Is there a reason a fix for this isn't built into the library yet? This seems to be a large issue.
Chiming in, during development:
Prop 'id' did not match
SSR vs CSR error in the console, this was resolved by setting instanceId={uuid}
(as suggested above)aria-activedescendant
error -- unfortunately this wasn't resolved for me when setting aria-activedescendant={undefined}
on both the Input
and MultiValueContainer
components π€· I also do notice a small rendering flicker/change difference between what is rendered server side vs client side in dev
yarn why next
ββ xtalk-pages@workspace:projects/xtalk-pages
ββ next@npm:14.1.0 [12c32] (via npm:14.1.0 [12c32])
yarn why react-select
ββ xtalk-pages@workspace:projects/xtalk-pages
ββ react-select@npm:5.8.0 [12c32] (via npm:^5.8.0 [12c32])
I also ran into this issue. I'm on reactv18 and I only see the issue when on production and in the Safari browser. All other browsers work well on production. The issue is affecting my multi-select dropdown and my custom single-select dropdown
I figured out that my issue is caused by my csp security. It prevents the inline styles from being added so the dropdowns look broken without the styles in place. I tried using nonce to resolve it but haven't been able to get the inline styles to be added with what I've tried so far.
Chiming in, during development:
- I initially started seeing
Prop 'id' did not match
SSR vs CSR error in the console, this was resolved by settinginstanceId={uuid}
(as suggested above)- I then started getting the
aria-activedescendant
error -- unfortunately this wasn't resolved for me when settingaria-activedescendant={undefined}
on both theInput
andMultiValueContainer
components π€·I also do notice a small rendering flicker/change difference between what is rendered server side vs client side in dev
yarn why next ββ xtalk-pages@workspace:projects/xtalk-pages ββ next@npm:14.1.0 [12c32] (via npm:14.1.0 [12c32]) yarn why react-select ββ xtalk-pages@workspace:projects/xtalk-pages ββ react-select@npm:5.8.0 [12c32] (via npm:^5.8.0 [12c32])
I had the same issue w/ nextjs 14.2.4 and react-select 5.8.0. I ended up setting the instanceId and downgrading to 5.7.7 to remove the aria-active-descendent warning.
Thanks! I can confirm that downgrading react-select to 5.7.7
also removed the console.error on my end
Hi, I had the same problem with next (13.2.1) and I found a workaround:
const MySelect = ({ placeholder, options, }: ProjectEditionSelectProps) => { const id = Date.now().toString(); const [isMounted, setIsMounted] = useState(false); // Must be deleted once // https://github.com/JedWatson/react-select/issues/5459 is fixed. useEffect(() => setIsMounted(true), []); return isMounted ? ( <Select id={id} options={options} placeholder={placeholder} className="project-edition-select-container" classNamePrefix="project-edition-select" /> ) : null; }; export default MySelect;
My workaround is to display the
<Select />
component only in client side. UseEffect() is only triggered client-side so theisMounted
is alwaysfalse
on server side.If you use the experimental version of Next 13, you may use use-client directive.
I'm not particularly happy with this "fix" but it leaves my console in peace.
A cleaner solution would be to use lazy load (dynamic) with ssr false.
it seems as though the advanced sortable multi-select example is not compatible with react-18. I have a project where it works as intended using react-16 then react-18 it bugs out on drag