Closed necolas closed 5 years ago
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
className
prop 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.
I have created a stylelint config that can be used to validate any CSS to be React Native compatible even if you only use it on the Web. I know that it's not the same as using 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};
...
`;
The
className
prop is going to be deprecated fromView
andText
(and anything else it might currently be available on). This prop was only supported as an escape-hatch for Twitter Lite's migration from aView
implemented atop of CSS Modules to the React NativeView
.Rough plan at the moment is:
className
in 0.10. Use ofclassName
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.