はじめに
React Native では stylesにスタイルを定義してかいているのですが、最近、Webの方でもReact Nativeと同じようにCSS in JSで書きだしてから、React Nativeを書く時にStyleSheet.createを忘れてしまう事案が発生しているので戒めに書きます。
あまり大した内容でなくすみません・・・。
const styles = {
container: {
marginLeft: '1rem',
backgroundColor: COLORS.BG_TEAL,
},
};
class App extends Component {
・・・・
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: COLORS.BG_TEAL,
},
});
class App extends Component {
・・・
そもそもStyleSheet.createは必要?
動作上は不要です。ですので、StyleSheet.createしなくとも動きますし、しない方がプレーンなオブジェクトで便利だったりしますが・・・・・・。
StyleSheet.createした方がいいよ!
StyleSheet.createをすることによって、オブジェクトはidで返るようになります。
これによってパフォーマンスの向上が見込めるので極力はやっておいた方がよいです。
const styles = StyleSheet.create({
container: {
flex: 1,
},
})
console.log(styles.container); // 6 などのプリミティブなnumberが返る
const styles = {
container: {
flex: 1,
},
};
console.log(styles.container); //ちゃんとオブジェクトが返る。{ flex: 1, }
プリミティブからオブジェクトへの復元
こう・・・、数値で返ってこられるとデバッグの時にこれなんやねんってなって困ることがあります。そこでflattenを使うことで元に戻すことができます。
const styles = StyleSheet.create({
container: {
flex: 1,
},
})
console.log(styles.container); // 6
const _container = StyleSheet.flatten(styles.container);
console.log(_container); //{ flex:1, }
ところが
console.log(Object.getOwnPropertyDescriptor(_container, 'flex'));
/*
configurable:false,
enumerable:true
value:1
writable:false
*/
ディスクプリタをみてみるとwritable: falseになっているため書き換えできませんので要注意です。
さらにはconfigurableもfalseなので消すこともできません。
オブジェクトの統合とプロパティの上書き
汎用的なコンポーネントを作成した時には、styleのオーバーライドをしたくなることがあります。
これはradiumと同じ記法でオーバーライドすることで解決できます。
ここでもflattenは活躍します(中身を確認する時は・・・)。
const styles = StyleSheet.create({
container: {
flex: 1,
margin: 30,
},
_container: {
flex: 2,
padding: 10,
}
});
console.log(StyleSheet.flatten([styles.container, styles._container]));
// { flex: 2, margin: 30, padding: 10, }
convenience properties
他には便利なプロパティも持っています。
absoluteFill
console.log(StyleSheet.absoluteFill); // 2
console.log(StyleSheet.flatten(StyleSheet.absoluteFill));
/*
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
*/
これはプリローダーやモーダルダイアログを出すのに良い感じに動いてくれます。
const styles = StyleSheet.create({
container: {
flex: 1,
},
_container: {
flex: 2,
},
overlay: {
backgroundColor: 'rgba(0, 0, 0, 0.7)',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
preloader: {
backgroundColor: 'rgba(255, 255, 255, 0.8)',
justifyContent: 'center',
alignItems: 'center',
height: 200,
width: 200,
borderRadius: 3,
},
});
const App = (props) => (
<View style={styles.container}>
{/* コンテンツ */}
<Main {...props} />
{/* オーバーレイ */}
<View style={StyleSheet.absoluteFill} >
<View style={styles.overlay} >
<View style={styles.preloader}>
<Text>ぐるぐる回るやつ</Text>
</View>
</View>
</View>
</View>
);
absoluteFillObject
absoluteFillと中身は同じですがこちらはオブジェクトで返ります。
console.log(StyleSheet.absoluteFillObject);
/*
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
*/
console.log(
Object.getOwnPropertyDescriptor(
StyleSheet.absoluteFillObject, 'top'
)
);
/*
configurable:false,
enumerable:true
value:object,
writable:false,
*/
具体的な使い方としては
const styles = StyleSheet.create({
container: {
flex: 1,
margin: 30,
...StyleSheet.absoluteFillObject,
},
});
console.log(StyleSheet.flatten(styles.container));
/*
bottom: 0,
left: 0,
position: 'absolute',
right: 0,
top: 0,
flex: 1,
margin: 30,
*/
となります。
hairlineWidth
それぞれのプラットフォームでもっとも薄い線を引く時に使える数値が設定されています。
console.log(StyleSheet.hairlineWidth); // 0.3333333
ただし、これは固定値ではなくプラットフォーム依存なので、
端末 | 数値 |
---|---|
iphone7Plus | 0.333333333 |
iphone7 | 0.5 |
iphone5 | 0.5 |
Nexus5x | 0.333333333 |
という感じで異なります。
横幅に依存してるんですかね?
const styles = StyleSheet.create({
_box: {
borderColor: '#3C3C3C',
borderWidth: StyleSheet.hairlineWidth,
},
});
という感じで利用することができます。
終わりに
以上で終了です!
CSS風なプロパティなんだーぐらいで納得してしまってあまりStyleSheetやStyleSheet.createを使う意義なども考えてこなかったのでいざこうやって勉強し直してみると意外と便利な機能もあるんだなと勉強になりました。
しかし、実際はStyleSheet.createさえ覚えとけばだいたい大丈夫だと思います!
StyleSheet.createルーチンすぎて、忘れやすいですが是非ともお忘れなくつけていただけますと幸いです。