Simplest way to cascade styles in react native

20.6k views Asked by At

I see that in react native if I set a fontFamily in a, for example, a View, the inner elements do not inherit it the property. Is it there a cascade concept available in react native styling? How do I accomplish it?

5

There are 5 answers

6
Maxwelll On

Pass styles as props to replicate the cascade in CSS. All child components can inherit a style prop to achieve this. It would be accomplished like:

const styles = StyleSheet.create({
  instructions: {
    fontSize: 16,
    textAlign: 'center',
    margin: 15,
  },
});

render() {
  return (
    <View style={styles.container}>
      <Text style={styles.instructions}>
      <ChildComponent
        cascadingStyle={styles}
      />
    </View>
  );
}

Here is an example I created to demonstrate rnplay.org/apps/dErxuQ

0
R01010010 On

Apparently at this moment a component can only inherit a property of a parent only if the parent is of the same type or at least also support the property to inherit. I was setting fontFamily in the main View component and wasn't being inherited in the Text children.

0
Dale Anderson On

The simplest way I have found to avoid repeating the style prop is to encapsulate in a component. For example:

const Item = ({ text }) => <Text style={{ padding: 10 }}>{text}</Text>
    
const Consumer = () =>
  <View>
    <Item text="Item 1" />
    <Item text="Item 2" />
    <Item text="Item 3" />
  </View>
0
webjaros On

I've achieved something like this by extracting style objects. Example below.

globalStyle.js

import {StyleSheet} from 'react-native';

export default StyleSheet.create({
    myView: {
        some view styles
    },
    myText: {
        some text styles
    },
});

localStyle.js

import {StyleSheet} from "react-native";
import globalStyle from "../globalStyle";

export default StyleSheet.create({
    ...globalStyle,
    myLocalView: {
        local view styles
    },
});

anotherLocalStyle.js

import {StyleSheet} from "react-native";
import {myText} from "../globalStyle";

export default StyleSheet.create({
    myLocalText: {
        ...myText,
        local text styles
    },
});
0
Matthew McCord On

I've had a similar kind of situation and we created a StyleClass that knows how to style each element type and individual elements by looking into predefined style objects.

We created custom wrappers for all the RN base elements which will all call to the StyleClass that knows how to find that elements base styles and any unique styles for its key/id.

Hope this helps in some way. Quick example might be like:

MyImage.jsx

import React from "react";
import { Image } from "react-native";
import { StylesClass } from "./StylesClass";

const styleClass = new StyleClass();

export class MyImage extends React.Component {
    render() {
        const { uniqueId, sourceUrl } = this.props;

        // finds styles by type "image" for base styles and "key" for unique styles
        let imageStyles = stylesClass.getElementStyle("image", uniqueId) || [];

        return (
            <Image
                source={{ uri: sourceUrl }}
                style={imageStyles}
            />
        );
    }
}

StyleClass.js (happy path no null / undefined checks)

const styles = {
  image: {
    // default imagestyles here
  },
  ...
};

const uniqueStyles = {
  image: {
    someUniqueId: {
      // unique styles for "someUniqueId" here
    },
  },
};

export class StyleClass {
  getElementStyle = (elementType, id) => {
    return [ ...styles[elementType], ...uniqueStyles[elementType][id] ];
  }
}

Then just use MyImage wherever you need Image.

Not necessarily cascading, more like css styling by id but our case had dynamic content coming in that needed to be styled and we didn't really have a cascading solution so we used default styles and then unique styles by each elements ID.