Bootstrap4のmarginとかpadding用のユーティリティクラスが手軽でつい使ってしまいます。

これね。mt-3みたいなやつ。

Menu
Bootstrap includes a wide range of shorthand responsive margin and padding utility classes to modify an element’s appearance.

Webの場合メリットとデメリットがあるのはわかります。スタイル直書きと対して変わらないし意味を持たないのでもしかしたらデメリットが多いかも。

んで、似たようなアプローチをReact Nativeで使いたいなーとふと思いました。

React Nativeでのレイアウトは基本的にはstyleに直書きするか、(コンポーネント間で)共通で用意したスタイル用のオブジェクトを渡すして共通化ぐらいしかできません。

だとしたら後者の共通オブジェクトなアプローチでmarginとpaddingのユーティリティを実現できるんじゃないかと思った次第です。

すでに誰がやってそうなもんだけど、ちょっと考えてみます。

使い方のイメージ

元々こうだったコードを、

render() {
  return (
    <View style={{ padding: 12, marginTop: 3, backgroundColor: 'white' }} />
  )
}

こうする感じです。

const styles = {
  // ...
  'p_4': { padding: 12 },
  // ...
  'mt_1': { marginTop: 3 },
  // ...
};

render() {
  return (
    <View style={{ ...styles.p_4, ...styles.mt_1, backgroundColor: 'white'  }} />
  )
}

stylesのところをちゃんとコードで生成してあげたら良い感じになるのではないかと思います。

ユーティリティ用オブジェクトを生成する

ループを回して作ってしまいます。

const styles = {};
const spacer = 3; // お好みで変える感じに

[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach((i) => {
  styles[`m_${i}`]  = { margin: spacer * i };
  styles[`mt_${i}`] = { marginTop: spacer * i };
  styles[`mb_${i}`] = { marginBottom: spacer * i };
  styles[`ml_${i}`] = { marginLeft: spacer * i };
  styles[`mr_${i}`] = { marginRight: spacer * i };
  styles[`mx_${i}`] = { marginHorizontal: spacer * i };
  styles[`my_${i}`] = { marginVertical: spacer * i };

  styles[`p_${i}`]  = { padding: spacer * i };
  styles[`pt_${i}`] = { paddingTop: spacer * i };
  styles[`pb_${i}`] = { paddingBottom: spacer * i };
  styles[`pl_${i}`] = { paddingLeft: spacer * i };
  styles[`pr_${i}`] = { paddingRight: spacer * i };
  styles[`px_${i}`] = { paddingHorizontal: spacer * i };
  styles[`py_${i}`] = { paddingVertical: spacer * i };
});

こうしてできたのが、これです。ちょっと長いですが、ちゃんとできていそうです。

使うときは指定に矛盾が出ないように気をつけて使う必要があるとは思いますが、矛盾が出てしまう場合はReact Nativeの仕様に従って決まるはず。paddingとpaddingTopだったらpaddingTopが優先されるとかだった気がします。違ったらすいません。

{
  "m_1":{
    "margin":3
  },
  "mt_1":{
    "marginTop":3
  },
  "mb_1":{
    "marginBottom":3
  },
  "ml_1":{
    "marginLeft":3
  },
  "mr_1":{
    "marginRight":3
  },
  "mx_1":{
    "marginHorizontal":3
  },
  "my_1":{
    "marginVertical":3
  },
  "p_1":{
    "padding":3
  },
  "pt_1":{
    "paddingTop":3
  },
  "pb_1":{
    "paddingBottom":3
  },
  "pl_1":{
    "paddingLeft":3
  },
  "pr_1":{
    "paddingRight":3
  },
  "px_1":{
    "paddingHorizontal":3
  },
  "py_1":{
    "paddingVertical":3
  },
  "m_2":{
    "margin":6
  },
  "mt_2":{
    "marginTop":6
  },
  "mb_2":{
    "marginBottom":6
  },
  "ml_2":{
    "marginLeft":6
  },
  "mr_2":{
    "marginRight":6
  },
  "mx_2":{
    "marginHorizontal":6
  },
  "my_2":{
    "marginVertical":6
  },
  "p_2":{
    "padding":6
  },
  "pt_2":{
    "paddingTop":6
  },
  "pb_2":{
    "paddingBottom":6
  },
  "pl_2":{
    "paddingLeft":6
  },
  "pr_2":{
    "paddingRight":6
  },
  "px_2":{
    "paddingHorizontal":6
  },
  "py_2":{
    "paddingVertical":6
  },
  "m_3":{
    "margin":9
  },
  "mt_3":{
    "marginTop":9
  },
  "mb_3":{
    "marginBottom":9
  },
  "ml_3":{
    "marginLeft":9
  },
  "mr_3":{
    "marginRight":9
  },
  "mx_3":{
    "marginHorizontal":9
  },
  "my_3":{
    "marginVertical":9
  },
  "p_3":{
    "padding":9
  },
  "pt_3":{
    "paddingTop":9
  },
  "pb_3":{
    "paddingBottom":9
  },
  "pl_3":{
    "paddingLeft":9
  },
  "pr_3":{
    "paddingRight":9
  },
  "px_3":{
    "paddingHorizontal":9
  },
  "py_3":{
    "paddingVertical":9
  },
  "m_4":{
    "margin":12
  },
  "mt_4":{
    "marginTop":12
  },
  "mb_4":{
    "marginBottom":12
  },
  "ml_4":{
    "marginLeft":12
  },
  "mr_4":{
    "marginRight":12
  },
  "mx_4":{
    "marginHorizontal":12
  },
  "my_4":{
    "marginVertical":12
  },
  "p_4":{
    "padding":12
  },
  "pt_4":{
    "paddingTop":12
  },
  "pb_4":{
    "paddingBottom":12
  },
  "pl_4":{
    "paddingLeft":12
  },
  "pr_4":{
    "paddingRight":12
  },
  "px_4":{
    "paddingHorizontal":12
  },
  "py_4":{
    "paddingVertical":12
  },
  "m_5":{
    "margin":15
  },
  "mt_5":{
    "marginTop":15
  },
  "mb_5":{
    "marginBottom":15
  },
  "ml_5":{
    "marginLeft":15
  },
  "mr_5":{
    "marginRight":15
  },
  "mx_5":{
    "marginHorizontal":15
  },
  "my_5":{
    "marginVertical":15
  },
  "p_5":{
    "padding":15
  },
  "pt_5":{
    "paddingTop":15
  },
  "pb_5":{
    "paddingBottom":15
  },
  "pl_5":{
    "paddingLeft":15
  },
  "pr_5":{
    "paddingRight":15
  },
  "px_5":{
    "paddingHorizontal":15
  },
  "py_5":{
    "paddingVertical":15
  },
  "m_6":{
    "margin":18
  },
  "mt_6":{
    "marginTop":18
  },
  "mb_6":{
    "marginBottom":18
  },
  "ml_6":{
    "marginLeft":18
  },
  "mr_6":{
    "marginRight":18
  },
  "mx_6":{
    "marginHorizontal":18
  },
  "my_6":{
    "marginVertical":18
  },
  "p_6":{
    "padding":18
  },
  "pt_6":{
    "paddingTop":18
  },
  "pb_6":{
    "paddingBottom":18
  },
  "pl_6":{
    "paddingLeft":18
  },
  "pr_6":{
    "paddingRight":18
  },
  "px_6":{
    "paddingHorizontal":18
  },
  "py_6":{
    "paddingVertical":18
  },
  "m_7":{
    "margin":21
  },
  "mt_7":{
    "marginTop":21
  },
  "mb_7":{
    "marginBottom":21
  },
  "ml_7":{
    "marginLeft":21
  },
  "mr_7":{
    "marginRight":21
  },
  "mx_7":{
    "marginHorizontal":21
  },
  "my_7":{
    "marginVertical":21
  },
  "p_7":{
    "padding":21
  },
  "pt_7":{
    "paddingTop":21
  },
  "pb_7":{
    "paddingBottom":21
  },
  "pl_7":{
    "paddingLeft":21
  },
  "pr_7":{
    "paddingRight":21
  },
  "px_7":{
    "paddingHorizontal":21
  },
  "py_7":{
    "paddingVertical":21
  },
  "m_8":{
    "margin":24
  },
  "mt_8":{
    "marginTop":24
  },
  "mb_8":{
    "marginBottom":24
  },
  "ml_8":{
    "marginLeft":24
  },
  "mr_8":{
    "marginRight":24
  },
  "mx_8":{
    "marginHorizontal":24
  },
  "my_8":{
    "marginVertical":24
  },
  "p_8":{
    "padding":24
  },
  "pt_8":{
    "paddingTop":24
  },
  "pb_8":{
    "paddingBottom":24
  },
  "pl_8":{
    "paddingLeft":24
  },
  "pr_8":{
    "paddingRight":24
  },
  "px_8":{
    "paddingHorizontal":24
  },
  "py_8":{
    "paddingVertical":24
  },
  "m_9":{
    "margin":27
  },
  "mt_9":{
    "marginTop":27
  },
  "mb_9":{
    "marginBottom":27
  },
  "ml_9":{
    "marginLeft":27
  },
  "mr_9":{
    "marginRight":27
  },
  "mx_9":{
    "marginHorizontal":27
  },
  "my_9":{
    "marginVertical":27
  },
  "p_9":{
    "padding":27
  },
  "pt_9":{
    "paddingTop":27
  },
  "pb_9":{
    "paddingBottom":27
  },
  "pl_9":{
    "paddingLeft":27
  },
  "pr_9":{
    "paddingRight":27
  },
  "px_9":{
    "paddingHorizontal":27
  },
  "py_9":{
    "paddingVertical":27
  }
}