What is the point of StyleSheet.create
Asked Answered
M

4

84

I'm reading the React Native docs / tutorial, and I'm wondering what the point of the StyleSheet.create function is.

For example, the tutorial has the following code:

const styles = StyleSheet.create({
  bigblue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

But I don't understand the difference between that and:

const styles = {
  bigblue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
};
Martino answered 11/8, 2016 at 1:42 Comment(0)
G
77

TL;DR Always use StyleSheet.create() when you can.

The answer by Nico is correct, but there is more to it.

To summarize:

  1. It validates the styles as mentioned by Nico
  2. As mentioned in the documentation:

Making a stylesheet from a style object makes it possible to refer to it by ID instead of creating a new style object every time.

  1. Also mentioned in the documentation:

It also allows to send the style only once through the bridge. All subsequent uses are going to refer an id (not implemented yet).

As you might know, sending the data across the bridge is a very costly operation that has significant impact on the performance of the application. So, using StyleSheet.create() you reduce the strain on the bridge.

Glucinum answered 11/8, 2016 at 3:54 Comment(6)
Aakash, I'm very new to React Native / mobile app development so I was not aware that sending data across the bridge was expensive. Thank you for your help, and for citing sources.Martino
Did you notice the "(not implemented yet)" note in the documentation referenced above? It's still there as at RN V0.43, April 2017. My reading of that is that it is NOT YET saving bridge traffic. Unless the doco is obsolete. I would still like to know if there really is any performance downside in skipping the StyleSheet.create(), and just using static (non-inline) styles... At least then they can be inspected and logged after being passed down the component stack!Swimmingly
@Swimmingly - they can still be inspected and logged. Use StyleSheet.flatten(...) to convert them back to an object in order to do so. The "not implemented yet" (which is still there as of 0.54) is contradicted by later assertions that there are performance benefits, so I suspect somebody just neglected to remove it when it was implemented. Should be relatively easy to profile, in any case, if you're worried about it... set up a view that changes regularly (or is created and destroyed a lot) and has lots of style attributes, and check processor usage using stylesheets or skipping them.Ferrate
.create still only validates in development and does nothing else. In production it just returns the object. See source code in repository.Moulmein
One other benefit is that StyleSheet validates the content within the style object as well. This means that should there be any errors in any properties or values in your style objects, the console will throw an error during compilation instead of at runtime.Containerize
"..sending the data across the bridge is a very costly...", what's the meaning of bridge in RN ?Vestment
D
44

StyleSheet.create does not add performance gains anymore.

https://github.com/DefinitelyTyped/DefinitelyTyped/issues/29265#issuecomment-430783289

quoting the github comment:

@alloy I understand what docs says, but can prove that code:

const myStyle: ViewStyle = { flex: 1 } export const FlexView:
React.SFC = (props) => <View style={myStyle}>{props.children}</View>

has almost same performance (even slightly faster) compared to

const s = StyleSheet.create({ flex: { flex: 1 } }) 
export const FlexView: React.SFC = (props) => <View style={s.flex}>{props.children}</View> 

because if you look at sources, you discover that latest chunk effectively extracted to this (see: https://github.com/facebook/react-native/blob/0.57-stable/Libraries/StyleSheet/StyleSheet.js#L373):

const s = { flex: { flex: 1 } }
export const FlexView = (props) => <View style={s.flex}>{props.children}</View>

And yes, in previous versions of RN it was global registry of styles, but it was even more slow, because it never crossed bridge border actually (proof from 0.55 branch) 😀

Dharana answered 25/10, 2018 at 17:21 Comment(1)
+1 as this is useful but you should explain why in a few words in your answer. The link might decay and then it just becomes a statement with no context or evidence :-)Beetroot
F
17

Here is there source code of create.

create<T: Object, U>(obj: T): {[key:$Keys<T>]: number} {
  var result: T = (({}: any): T);
  for (var key in obj) {
    StyleSheetValidation.validateStyle(key, obj);
    result[key] = ReactNativePropRegistry.register(obj[key]);
  }
  return result;
}

I am not an expert of React in any. I actually never used it but here are my insights. It seems that create does some kind of validation over your keys and register them to React.

I think you could skip the validation by simply not calling create but I'm not sure what ReactNativePropRegistry.register does exactly.

Reference to the source

Faa answered 11/8, 2016 at 1:56 Comment(1)
refer to ethanneff answer, source changed for newer versions, now it seems to just return the very same object: github.com/facebook/react-native/blob/0.57-stable/Libraries/…Sliwa
P
4

As @Mentor pointed out in the comments:

.create still only validates in development and does nothing else. In production it just returns the object. See source code in repository.

source code

create<+S: ____Styles_Internal>(obj: S): $ObjMap<S, (Object) => any> {
  if (__DEV__) {
    for (const key in obj) {
      StyleSheetValidation.validateStyle(key, obj);
      if (obj[key]) {
        Object.freeze(obj[key]);
      }
    }
  }
  return obj;
}

I think this comment deserves to be more noticeable. So I post it as an answer.

Additionally, I'd like to point out that validation - is a good thing, but there is another, better way to validate - Typescript:

const styles = StyleSheet.create({
  someViewStyle: { ... },
  someTextStyle: { ... },
})

can be replaced with

import { ..., ViewStyle, TextStyle } from 'react-native';

interface Styles {
  someViewStyle: ViewStyle,
  someTextStyle: TextStyle,
}
const styles = {
  someViewStyle: { ... },
  someTextStyle: { ... },
}

And it's not just static-time check, it also allows to discriminate between ViewStyle and TextStyle.

But there are more lines of code. So, personally, I prefer to go without styles object, if possible:

const someViewStyle: ViewStyle = { ... },
const someTextStyle: TextStyle = { ... },
Papal answered 24/12, 2020 at 19:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.