react-select
react-select copied to clipboard
Some css styles are not created in production but work in development
Hello,
We are hitting an odd css/emotion issue in production, while the component works great in development. We've tried this on v2.0.0-v.2.2.0 and its the same issue with all of them.
The dynamic css rules for the outer divs never get created in the emotion stylesheet. They are, however, set on the divs in the DOM. The rest of the dynamic css rules (e.g. on the options when you click on the control) do get created in the emotion stylesheet. This only happens on a few pages in our app, while other parts work as expected. Here is a screenshot of the the DOM when the page loads.
You'll notice that the select outermost div was assigned a classname of css-10nd86i
, but that css rule does not actually exist in the DOM. Using the javascript console to dump out the emotion stylesheet, you'll notice in this screenshot that the rules are totally empty in the stylesheet.
Now if you click on the select control to open it, the css rules for the options list all get created:
So the options get styled correctly, but the primary select component does not. I've tried various versions of emotion, react-select, react, etc., but the issue still persists. We've had to swap out this component in production for the time being, but would like to figure this out. Any help would be greatly appreciated.
@jjlauer are there any key similarities between the pages where this happens? Any information you could provide us to narrow down a reproducible case for this would be helpful; and if possible a codesandbox reproduction.
This usually happens when you're trying to instantiate emotion across contexts, like in an iframe or through server side rendering for example.
Made some headway. On the page in our app that works, it's a very complicated page and the user would only see the Select component if they were already on the page for a few seconds (e.g. javascript all loaded, before Select ever rendered).
On the page this issue occurs the Select component is rendered immediately when the browser loads the page. If I delay the Select from being rendered for even just 100ms (via setTimeout) then it renders correctly. Any ideas on what could be causing something like that and why even just 100ms delay in React rendering the Select component would fix it?
@jjlauer Did you ever figure this out? I'm having the same issue. The selector is properly styled in a development environment, but in a production build none of the emotion stylesheets get injected into the head.
@ryanrombough Unfortunately no. Only workaround is what i mentioned above -- you have to delay rendering of the widget so it doesn't occur on the first react render().
@jjlauer I just tried implementing a 500ms delay on rendering but it did not solve the issue for me. Guess I'll keep digging. Thanks!
I have narrowed the cause of my issue down to the minification step in my Webpack v4 build. Here's the stack overflow question I created to try to find out why this is happening.
Hmm.. did turning off minimize in webpack fix your production issue?
I also had issues w/ the css not being injected into the header, but adding a delay (of any use of react-select) on the initial react render fixed it. It feels like a race condition between Emotion fully initializing before react-select uses it.
On Wed, Apr 3, 2019 at 6:10 PM Ryan Rombough [email protected] wrote:
I have narrowed the cause of my issue down to the minification step in my Webpack v4 build. Here's the stack overflow question https://stackoverflow.com/questions/55505056/why-would-webpack-4-minification-prevent-styles-for-react-select-component .
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JedWatson/react-select/issues/3309#issuecomment-479677022, or mute the thread https://github.com/notifications/unsubscribe-auth/AAjwAtXg0d-2BhpFcJqVxX0oGVuaiV4Dks5vdSbOgaJpZM4ZmF0W .
Yea, but that's not really a solution for us because our bundle is too large when not minified. I tried implementing the delay you suggested but could not get it to work.
Hi @jjlauer I am facing the same CSS not being applied in Production. If you can kindly help me with the code snippet for setting the delay in rendering the react-select it would be extremely helpful!! Thank you.
I have the same issues
I managed to fix the issue by adding classNamePrefix
which seems to force react-select
to add the classNames to the sub-components in production
<Select
classNamePrefix='select'
{...}
/>
Before
<div class=" css-1hwfws3">
...
</div>
After
<div class="select__value-container select__value-container--is-multi select__value-container--has-value css-1hwfws3">
...
</div>
Thanks for letting us know @NearHuscarl!
@NearHuscarl's solution didn't solve my problem. Have used classNamePrefix
for a while, and the issue remains the same.
@jjlauer how did you implement the delay?
@bladey is there a way to "force" the CSS to be loaded programatically?
Getting desperate here 😅
Here is how I implemented a very simple delay to rendering. Here's the main react component (e.g. top-level entrypoint). I originally was rendering the ReportsPanel
component, but developed a simple wrapper component i called DelayedRender
that is now responsible for rendering it instead.
class ReportsPage extends Component {
constructor() {
super();
}
render() {
const { dispatch, query, user, accounts } = this.props;
return (
<DelayedRender>
<ReportsPanel
dispatch={dispatch}
query={query}
user={user}
accounts={accounts}
active={true}
/>
</DelayedRender>
);
}
}
Here is DelayedRender:
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
export default class DelayedRender extends PureComponent {
constructor() {
super();
this.state = {
render: false
};
}
componentDidMount() {
const { time } = this.props;
setTimeout(() => this.setState({ render: true }), (time || 400));
}
render() {
const { children } = this.props;
const { render } = this.state;
if (!render) {
return null;
}
return children;
}
}
This seems like it's still present in [email protected].
This problem has reappeared for us in 4.2.1
@rushilsrivastava are you folks using react-windowed-select
as well as react-select
? My team has a hunch it may be the former causing issues.
Confusingly, downgrading just react-windowed-select
to use react-select
3 seems to resolve the issue.
@wegry We aren't using react-windowed-select
, still having a hard time pinpointing what package/code change caused this since downgrading to 4.1.0 doesn't seem to work for us either. We will give react-select
v3 a shot though and report back here.
For the time being, we are using @jjlauer's solution.
Greetings @wegry , @rushilsrivastava , @jjlauer , or anyone else,
Would any of you be willing to share your package.json to help us recreate the issue?
@wegry Can you look at your yarn.lock
or package-lock.json
and see if anything depends on Emotion besides react-select
?
@wegry I looked into your package.json
and it looks like you have react-windowed-select@^2.0.2
installed which references react-select@3
. Can you try upgrading that to [email protected]
and see if it makes a difference? react-windowed-select@2
depends on react-select@3
, but react-windowed-select@3
depends on react-select@4
, so that mismatch could be a potential cause of the issue.
@Methuselah96 let me post my whole package.json and yarn.lock as a gist. The version above is current after the downgrade. I'll send the version reproing this instead. My mistake.
Just so it's clear that I added a gist (not sure if edits notify), https://gist.github.com/wegry/5b2d97db8257b459b95c08c1e3153dd5. @Methuselah96
@wegry Yeah, I'm not seeing anything suspicious. At this point the only thing to do is to try to recreate the issue in a public repo so that we can dig into it more. Are you using Webpack? Are there CSS loaders that you're using that could be affecting this?
@Methuselah96 I've unfortunately been unable to repro this at a smaller scale than the app it's occuring in.
Are you using Webpack?
Yeah, [email protected].
I'm thinking in our case, it's because we have two+ chunks that pull in react-select. The way we repro the styles visibly being broken (and not present in the dom) is
- Prod build
- cache free refreshing chunk A where we import
react-select
's default export. - Navigating to a page (in a different chunk) where a wrapped component containing three different versions of react-select (one of which is
'react-select/creatable'
) and react-windowed-select is used.
There might be multiple emotion caches being used in our case?
Are there CSS loaders that you're using that could be affecting this?
I would think CSS loaders wouldn't affect this, especially since react-select doesn't package css, right?
I had the issue with the styles not working with production build after some of my components were inserted into a shadow root. What worked for me was to add CacheProvider
from emotion somewhere in the application root.
Please see https://github.com/JedWatson/react-select/issues/3680#issuecomment-809518245 for more details.
Hope this helps.
Any update or solution on this issue? Apart from delay rendering
I had this issue with react-select
4.3.0, and @NearHuscarl 's solution https://github.com/JedWatson/react-select/issues/3309#issuecomment-678728542 worked for me!
stack:
- gatsby (3.4.1)
- react (11.4.0)
- emotion (gatsby-plugin-emotion: 6.5.0)
- twin.macro (2.4.1)
- react-select (4.3.0)
issue:
- a route page (
/myRoute
) in my app contained areact-select
component - on other pages, hovering on gatsby links
<Link to="/myRoute">
caused the styles of unrelated components on the other pages to break.- this only happened on production builds. in the inspector, I could see that the links to
/myRoute
caused chunk load errors on hover. - likely due to gatsby's behavior of chunk splitting in prod builds, and pre-fetching chunks when hovering links.
- this only happened on production builds. in the inspector, I could see that the links to
solution:
- adding a
classNamePrefix="react-select"
to our<Select
component made the other pages' pre-fetched loaded css chunks not fail.
I was able to come up with a simple workaround, but can only guess as to why it works.
TLDR
I hid a <Select>
in the _app.tsx
outside of the <Component>
.
// _app.tsx
function MyApp({Component, pageProps}: AppProps) {
return (
<>
<div>
// This is the User Context Provider from auth0
<UserProvider>
<div className="app-container">
<Component {...pageProps} />
</div>
</UserProvider>
// Hide this select from view
<div style={{display: "none"}}>
// This select is put here to get the emotion styles rendered in production */}
<Select
instanceId={"rendered-select"}
value={{label: "none", value: "none"}}
options={[{label: "none", value: "none"}]}
onChange={() => null}
/>
</div>
</div>
</>
)
}
export default MyApp
My guess as to why this works
I had this issue running react-select
4.3.1 on next.js and tried the previously mentioned solutions but they did not work (delayed rendering https://github.com/JedWatson/react-select/issues/3309#issuecomment-714758497 worked occasionally, but not every time).
Since the delayed rendering worked occasionally, I thought it could be a caching issue (or some other race condition related to the inner workings of react/next.
I am using auth0
and wrapping every page in the UserProvider
from auth0
in my _app.tsx
. UserProvider
then provides context via a useUser
.
// Every page needing app user context uses this wrapper
const PageWrapper = ({children, serializedDsUser} : PageWrapperProps) => {
// authUser is the auth0 user
const { user: authUser, isLoading } = useUser()
// dsUser is the app's user object
const dsUser = serializedDsUser ? JSON.parse(serializedDsUser) : null
const context: UserSessionContextValues = {
authUser: authUser ? authUser : null,
dsUser,
isLoggedIn: authUser ? true : false
}
return (
<div>
{isLoading ?
<AppLoader isLoading />
:
<UserSessionContext.Provider value={context}>
{children}
</UserSessionContext.Provider>
}
</div>
)
}
export default PageWrapper
Each page does not render until user data returned by useUser
completes loading. Without spending many more hours tracing this bug down, I'm guessing something having to do with conditionally rendering the pages and subsequently any nested <Select>
components based on user state and SSR is causing some sort of race condition with the caching (as mentioned by @jjlauer https://github.com/JedWatson/react-select/issues/3309#issuecomment-479678164).
Hope this saves someone some time.
None of the above with hiding in _app.tsx or setting a classname prefix works for me on nextjs currently on client route push. Has anyone been able to get this working recently?
delayed rendering doesnt work either i cant get the css to show up if im including the select conditionaly based on state