Inheriting styles in React Native components
When creating React Native components it is a good idea to think about reusability. It is common to make components that have some base style, but that can also be styled upon use. As we will see, we can leverage some useful JavaScript features to achieve this in a clean way.
Styling in React Native
In React Native we use the style
prop to declare our styles, essentially emulating the way it’s done on the web but with some differences, mainly that it is written in camel case. Another thing to note is that we need to pass an object with styles (thats why we need the double {{}} in the style prop):
const MyComponent = (props) => {
return <Text style={{backgroundColor: 'green'}}>{props.title}</Text>
}
<MyComponent title="Hello world"/>
Now say we want to pass some custom styles to this component when we use it:
<MyComponent title="Hello world" style={{backgroundColor: 'red'}}/>
The style
being passed will be available under props.style
in the component. But how do we merge the styles that we passed with the style already in the component?
Merging styles in a component
First we can use ES6 object destructuring, where we lift out the style
and title
from the props
object. To then merge our styles we can use the ES6 spread syntax to spread the contents of the style
object into the object being passed to the style prop in the component:
const MyComponent = ({style, title}) => {
return <Text style={{backgroundColor: 'green', ...style}}>{title}</Text>
}
What happens is that we pass one new object containing all our styles to the style
prop. This works, but there is a better way:
const MyComponent = ({style, title}) => {
return <Text style={[{backgroundColor: 'green'}, style]}>{title}</Text>
}
Instead of passing one object containing all our styles we are now passing an array of style objects to the style
prop. What we gain is precedence: the last added styles object will be evaluated last, which is desired if we intend for the passed styles to be inherited by the component.
Furthermore, we are now able to add as many style objects as we want and still maintain readability:
const MyComponent = ({style, title}) => {
return <Text style={[{backgroundColor: 'green'}, styles.myText, style]}>{title}</Text>
}
const styles = StyleSheet.create({
myText: {
color: 'white'
}
})
But what happened to the rest of the props?
What if we waned to pass additional props to our component? Do we have to lift our each one using destructuring to make them available inside out component? No, there is an easier way:
const MyComponent = ({style, title, ...rest}) => {
return <Text {...rest} style={[{backgroundColor: 'green'}, styles.myText, style]}>{title}</Text>
}
const styles = StyleSheet.create({
myText: {
color: 'white'
}
})
...<MyComponent title="Hello world" style={{backgroundColor: 'red'}} onPress={() => console.log('Howdy')} />
The ...rest
will make any other props available in the function. These can then be spread using {...rest}
onto the component that’s being returned. This way we can use the onPress
prop and make it work in our component.
Hope this was helpful, stay tuned for more! And don’t forget to follow!