Search code examples
reactjsreact-nativetailwind-cssatomic-design

React Native Components Override styles "leaking"


I'm trying to build my own component library specific to my React Native app using the Atomic Design Methodology, so I have small components like Paragraph, Title, Wrap, Button, Subtitle etc. in a single file called "Atoms". I can import them in my other components like so:

import { Paragraph, Title, Wrap, Button, Subtitle } from "../Atoms";

I'm building them using tailwind-react-native-classnames. It's a great package using Tailwind CSS with lots of useful features like platform prefixes and dark mode support.

Now, sometimes I need unique style changes on these components, so I have a style prop to mix the style Object to one, it works like this:

 <Subtitle style={tw`pt-20`}>Some Text</Subtitle>

And in the component:

 const Subtitle = ({ style, children }) => (
  <Text style={Object.assign(tw`text-xl mb-3 text-octonary dark:text-white`, style)}>
    {children}
  </Text>
);

This works well, any style can be overwritten, it's intuitive to work with and gives me lots of freedom. But here's the problem, the changes (inconsistently, and not every component) seems to effect the same components on other Screens. So in the above example the tw`pt-20` translates to paddingTop: 5rem and applies it to other places, other Screens, with the same component, that shouldn't even have this style applied to it.

Why is this happening? Is it cashed somehow? And how can I fix it?

Thanks in advance for any help/suggestions.


Solution

  • I found a solution, thanks to @Abe I experimented using tw.style(). So instead of this:

    const Subtitle = ({ style, children }) => (
      <Text
        style={Object.assign(tw`text-xl mb-3 text-octonary dark:text-white`, style)}
      >
        {children}
      </Text>
    );
    

    I did this:

    const Subtitle = ({ style, children }) => (
      <Text
        style={tw.style(
          "text-xl",
          "mb-3",
          "text-octonary",
          "dark:text-white",
          style
        )}
      >
        {children}
      </Text>
    );
    

    It's not as close to normal Tailwind CSS since every class needs separate quotes and also be separated by commas, but it works! But then I went even further and did this:

    const Subtitle = ({ style, children }) => {
      const s = tw`text-xl mb-3 text-octonary dark:text-white`;
      return <Text style={tw.style(s, style)}>{children}</Text>;
    };
    

    It's more compact, I can code vanilla tailwind and no "leaking". So win-win-win!