The className prop is going to be deprecated from View and Text (and anything else it might currently be available on). This prop was only supported as an escape-hatch for Twitter Lite's migration from a View implemented atop of CSS Modules to the React Native View.
Rough plan at the moment is:
className in 0.10. Use of className will start printing warnings in the console.className in 0.11.If you're relying on this undocumented escape-hatch please let me know the details.
I've used className in the past to get a reference to the dom node when a browser only work around was necessary. I tried to get the dom node trough the ref but couldn't find it.
Also I've used it in the past to apply css classes that have browser specific psuedo selectors to hide scrollbars for example. Since I can't find anything about using css psuedo classes in react native which doesn't make sense but is needed in the example above.
Any recommendations?
className is useful escape-hatch for browser only styles. I don't know how to float an image in another way. Sure RNW can be strict, but the evolution is incremental.
Maybe some prefix for web-only inline styles can fix it.
Just an update, I've currently replaced all views that used the className prop as escape hatch with divs which just seems to work like a react component instead of a react native web component. So a .web.js file could contain mixed components like: <View>, <Text>, <div>, <h2> etc.
e.g.
render() {
return <div className={'not-an-escape-hatch-but-mixed-components'}><Text>Hello</Text></div>;
}
Mixing with classNames is not safe
I don't know how to float an image
Use the float style
I know that I'm very late to the discussion as I haven't for some reason noticed this before.
I have some projects that are using React Native Web and CSS modules. If the className gets removed, then is there any easy way to bring back the support, for example enable with an option or a possibility to create a small library that adds support for className?
I personally really like the idea that RNW would be compatible with the Web and Web React with allowing the usage of className like it has done so far.
https://reactjs.org/docs/faq-styling.html#how-do-i-add-css-classes-to-components
Note that this functionality is not a part of React, but provided by third-party libraries. React does not have an opinion about how styles are defined; if in doubt, a good starting point is to define your styles in a separate *.css file as usual and refer to them using className.
Going forward, you should never mix CSS modules with React Native components. In practice that means doing this…
import classes from './styles.css';
const A = () => <View className={classes.root} />
…will have no impact on the presentation. But you can continue to use CSS modules with React DOM components, and those React DOM components can be used in the same web app as React Native components.
Going forward, you should never mix CSS modules with React Native components.
My case is a bit different because I'm using CSS Modules + Sass or PostCSS in my React Native projects. I have also been planning on starting to migrate Web projects to use RNW, but if the support for CSS modules is removed, then I can not share any components between my RN projects and Web.
I know that this is not a problem for most of the users, but it breaks the RN<->Web compatibility for me and a few other people who are using CSS pre-processors in React Native and might possibly want to render the code in a browser.
Here's the link to my React Native CSS modules project if you want to read more:
https://github.com/kristerkari/react-native-css-modules
If your project is compatible with RN shouldn't it be compatible with RNW without relying on the className prop being passed to the DOM?
If your project is compatible with RN shouldn't it be compatible with RNW without relying on the
classNameprop being passed to the DOM?
I have created a Babel plugin that is used only on the React Native side to transform className prop to style. That way you can use className for both RN and Web.
That way I can use CSS modules on both platforms together with RNW.
To give you a better idea, I have created simple example apps to show how you can render regular CSS or Sass on Android, iOS, and Web:
https://github.com/kristerkari/react-native-css-modules#example-apps
CSS modules doesn't have the same safety or resolving characteristics as React Native styles.
CSS modules doesn't have the same safety or resolving characteristics as React Native styles.
I am fully aware of that, but it also does not mean that you can not create well functioning Web apps using CSS modules.
I'm ok with the className support not being enabled by default, but it would be nice if there was a way to opt-in with a setting to enable it, or something similar.
@kristerkari You can make a higher order component with setNativeProps in useEffect. You can also leverage nativeID.
There are a few additional things that I would like to be considered related to RNW's CSS modules support.
style property in React Native, but it's just presented differently to the user.StyleSheet, but better than using CSS modules without any restrictions.className from RNW obviously means that no CSS pre/post-processor can be used with it, making it less flexible as you can not do things like scripting in Sass or use libraries like postcss-preset-env, etc.Looks like this change also affects the use of styled components with RNW.
An example from my project:
const Container = styled(View)`
flex: 1;
justify-content: center;
align-items: center;
background-color: #fff;
`;
↓
Warning: Using the "className" prop on <View> is deprecated.
so @necolas any chance of re-opening this issue and adding a setting to RNW that would remove the warnings and enable className?
I would be just fine with the className being disabled by default and not the recommended way to do styling with RNW, but that you could opt-in to use it when needed.
It seems to me that removing className support completely will just break a lot of libraries that could otherwise be compatible with RNW.
@necolas would be great to have support for styled-components or a way to disable the warnings
Use styled-components/native. But you're better off using RN directly
Use styled-components/native. But you're better off using RN directly
Ah, for some reason I did not notice the /native in the import because it was rendering fine in React Native without the /native in the import.
btw. @necolas the styled-component implementation got me thinking about one idea. Do you think that it would be possible to create a plugin that would turn CSS from a file to style objects that run through the RNW Stylesheet.create and that way is rendered the same way as other styles? Kind of the same idea as with DSS and how it resolves the classes inside className etc.
That way the user would still have the option to use CSS files and there would be no need to expose className prop.
When I try to use styled-components/native it throws an error about react-native not being what it's expecting. I guess that this has to do with aliasing react-native with react-native-web?
./node_modules/styled-components/native/dist/styled-components.native.esm.js
Attempted import error: 'react-native' does not contain a default export (imported as 'reactNative').
Did anyone get this working properly?
While I appreciate the safety and predictability that RN styles provide, and media queries are not really in the spirit of RNW, I have not found a way to reasonably and correctly server render my app without shipping some media query based styles outside of RNW. I was hoping to rely on @kristerkari's react-native-css-modules to do that.
I would be very interested in ideas for better ways we could work on to server render responsive apps with RNW, but I don't have anything.
While I appreciate the safety and predictability that RN styles provide, and media queries are not really in the spirit of RNW, I have not found a way to reasonably and correctly server render my app without shipping some media query based styles outside of RNW.
true, I don't think that CSS media queries can be supported if the className prop gets removed. The only option would be to do the media queries with Javascript.
As I said before, this change really removes a lot flexibility from RNW by restricting the styles to the StyleSheet API.
Well there are hackier options like:
<MediaQueryWrapper>/<ApplyClass> component that just renders a <div> with the class in the .web.js version and a View with the styles otherwiseWell there are hackier options like:
Those are valid workarounds/hacks for the problem, but they will also mean that the user needs to add code for the workaround to his/her project.
My goal with the React Native CSS modules library is to give the user a simple way to style React Native apps with plain CSS or CSS processors. It really sucks if the user has to do some hacks to get that working on the Web.
In my opinion the only suitable ways to tackle the problem would be to either add opt-in setting for the className support OR create some kind of plugin that would transform CSS->StyleSheet + transform CSS media queries to something that RNW could support.
As I said before, this change really removes a lot flexibility from RNW by restricting the styles to the StyleSheet API.
No, it doesn't. You can apply styles using data-* attribute selectors. But as I mentioned, your project won't produce consistent styles between web and RN because you're just generating CSS modules code.
No, it doesn't. You can apply styles using
data-*attribute selectors. But as I mentioned, your project won't produce consistent styles between web and RN because you're just generating CSS modules code.
As mentioned before, there are workarounds, but those workarounds require the user to write extra code that is Web specific. You can not use the same CSS styles for both React Native and Web unless you use the StyleSheet API.
This is giving me a lot of trouble because we use StyledComponents and we reuse components on web and app. What would be the correct way to still be able to use these 2? I can not use styledComponents/native because we are using them on the web as well.
@mglavall StyledComponents is an unnecessary abstraction from day one. It was created as slow and buggy wrapper over glamour. In JavaScript, we don't need to emulate CSS text-based syntax. Anyway, with React Native Web, it's pointless to use it over StyleSheet. The correct way is to not use StyledComponents. It's leaky abstraction (google it). For styling, there is style or emotions css prop. Misusing components and their props for styling is possible but wrong.
@mglavall maybe have a look at https://github.com/callstack/react-theme-provider very easy to build something like styled components for react-native/web
@mglavall StyledComponents is an unnecessary abstraction from day one. It was created as slow and buggy wrapper over glamour. In JavaScript, we don't need to emulate CSS text-based syntax. Anyway, with React Native Web, it's pointless to use it over StyleSheet. The correct way is to not use StyledComponents. It's leaky abstraction (google it). For styling, there is style or emotions css prop. Misusing components and their props for styling is possible but wrong.
I don't think that response is helping anyone in any way. ´Don't use it´does not help all the people that are already using it. Thanks for the explanation, though
"Don't use it" or "You are doing it wrong" is often the best answer ever. Some things are unfixable. For example GraphQL SDL or the State (socialism) or fiat money. To illustrate that pattern, check https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3 Hope you will understand why I wrote that response.
Styled Components removes the extra guff required if we'd like to build readable and clear markup.
Almost any component tends to be given a meaningful name, even if it's just a component that takes styles and doesn't do anything functionally. It removes the existence of <View style={timelineFooterStyles} /> everywhere and we instead tend to end up with the much clearer and more readable <TimelineFooter/>. This is _much_ more readable when a few View components are nested or adjacent each other.
If we'd like to replicate this with the StyleSheet API, when defining our "styled" components, everyone in the team would have to remember to handle children and other props. Styled Components handles this for us, not only ensuring there's less scope for bugs but making sure our "styled" component definitions are simpler with less guff.
@steida, I'll google the leaky abstraction issue, but my concern is with the Styled Components paradigm being written off as not needed or not useful.
I experimented with styled components API a lot in the past. The main problem is clashes among component props and style props which is unsolvable.
'
much clearer and more readable
You wanted to say "which I am more familiar with". Sure you can make a reusable component but repeating yourself is far less expensive than the wrong abstraction.
Imagine a simple Text component. It's not as simple, because text can and will have different sizes, fonts, centering. Are you going to replicate everything via props? Sure you can..., but again, read something about utility CSS.
I was using even things like <Box width= but it was not as flexible as <View style=[a, b, c
I did something like this, and it seems to work – maybe there are drawbacks, I don't know... 😅
// SharedComponent.ts
import styled from 'styled-components';
import { Theme } from '../styles/types';
import { Text } from 'react-native'; // I still use the `react-native-web` webpack alias for the web project, although it might not even be necessary
const webOrNativePrimitive = (defaultTag?: string, defaultPrimitive?: any) => {
return (typeof navigator !== 'undefined' && navigator.product !== 'ReactNative') || process.env.NODE ? defaultTag || 'p' : defaultPrimitive || Text;
};
export const Typography = styled(webOrNativePrimitive())<{ type?: string; os?: string; theme: Theme }>`
font-family: ${({ theme }: { theme: Theme }) => theme.font.defaultFont};
...
`;
Most helpful comment
Use styled-components/native. But you're better off using RN directly