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

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

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

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

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

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

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

使い方のイメージ

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

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

こうする感じです。

 1const styles = {
 2  // ...
 3  'p_4': { padding: 12 },
 4  // ...
 5  'mt_1': { marginTop: 3 },
 6  // ...
 7};
 8
 9render() {
10  return (
11    <View style={{ ...styles.p_4, ...styles.mt_1, backgroundColor: 'white'  }} />
12  )
13}

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

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

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

 1const styles = {};
 2const spacer = 3; // お好みで変える感じに
 3
 4[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach((i) => {
 5  styles[`m_${i}`]  = { margin: spacer * i };
 6  styles[`mt_${i}`] = { marginTop: spacer * i };
 7  styles[`mb_${i}`] = { marginBottom: spacer * i };
 8  styles[`ml_${i}`] = { marginLeft: spacer * i };
 9  styles[`mr_${i}`] = { marginRight: spacer * i };
10  styles[`mx_${i}`] = { marginHorizontal: spacer * i };
11  styles[`my_${i}`] = { marginVertical: spacer * i };
12
13  styles[`p_${i}`]  = { padding: spacer * i };
14  styles[`pt_${i}`] = { paddingTop: spacer * i };
15  styles[`pb_${i}`] = { paddingBottom: spacer * i };
16  styles[`pl_${i}`] = { paddingLeft: spacer * i };
17  styles[`pr_${i}`] = { paddingRight: spacer * i };
18  styles[`px_${i}`] = { paddingHorizontal: spacer * i };
19  styles[`py_${i}`] = { paddingVertical: spacer * i };
20});

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

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

  1{
  2  "m_1":{
  3    "margin":3
  4  },
  5  "mt_1":{
  6    "marginTop":3
  7  },
  8  "mb_1":{
  9    "marginBottom":3
 10  },
 11  "ml_1":{
 12    "marginLeft":3
 13  },
 14  "mr_1":{
 15    "marginRight":3
 16  },
 17  "mx_1":{
 18    "marginHorizontal":3
 19  },
 20  "my_1":{
 21    "marginVertical":3
 22  },
 23  "p_1":{
 24    "padding":3
 25  },
 26  "pt_1":{
 27    "paddingTop":3
 28  },
 29  "pb_1":{
 30    "paddingBottom":3
 31  },
 32  "pl_1":{
 33    "paddingLeft":3
 34  },
 35  "pr_1":{
 36    "paddingRight":3
 37  },
 38  "px_1":{
 39    "paddingHorizontal":3
 40  },
 41  "py_1":{
 42    "paddingVertical":3
 43  },
 44  "m_2":{
 45    "margin":6
 46  },
 47  "mt_2":{
 48    "marginTop":6
 49  },
 50  "mb_2":{
 51    "marginBottom":6
 52  },
 53  "ml_2":{
 54    "marginLeft":6
 55  },
 56  "mr_2":{
 57    "marginRight":6
 58  },
 59  "mx_2":{
 60    "marginHorizontal":6
 61  },
 62  "my_2":{
 63    "marginVertical":6
 64  },
 65  "p_2":{
 66    "padding":6
 67  },
 68  "pt_2":{
 69    "paddingTop":6
 70  },
 71  "pb_2":{
 72    "paddingBottom":6
 73  },
 74  "pl_2":{
 75    "paddingLeft":6
 76  },
 77  "pr_2":{
 78    "paddingRight":6
 79  },
 80  "px_2":{
 81    "paddingHorizontal":6
 82  },
 83  "py_2":{
 84    "paddingVertical":6
 85  },
 86  "m_3":{
 87    "margin":9
 88  },
 89  "mt_3":{
 90    "marginTop":9
 91  },
 92  "mb_3":{
 93    "marginBottom":9
 94  },
 95  "ml_3":{
 96    "marginLeft":9
 97  },
 98  "mr_3":{
 99    "marginRight":9
100  },
101  "mx_3":{
102    "marginHorizontal":9
103  },
104  "my_3":{
105    "marginVertical":9
106  },
107  "p_3":{
108    "padding":9
109  },
110  "pt_3":{
111    "paddingTop":9
112  },
113  "pb_3":{
114    "paddingBottom":9
115  },
116  "pl_3":{
117    "paddingLeft":9
118  },
119  "pr_3":{
120    "paddingRight":9
121  },
122  "px_3":{
123    "paddingHorizontal":9
124  },
125  "py_3":{
126    "paddingVertical":9
127  },
128  "m_4":{
129    "margin":12
130  },
131  "mt_4":{
132    "marginTop":12
133  },
134  "mb_4":{
135    "marginBottom":12
136  },
137  "ml_4":{
138    "marginLeft":12
139  },
140  "mr_4":{
141    "marginRight":12
142  },
143  "mx_4":{
144    "marginHorizontal":12
145  },
146  "my_4":{
147    "marginVertical":12
148  },
149  "p_4":{
150    "padding":12
151  },
152  "pt_4":{
153    "paddingTop":12
154  },
155  "pb_4":{
156    "paddingBottom":12
157  },
158  "pl_4":{
159    "paddingLeft":12
160  },
161  "pr_4":{
162    "paddingRight":12
163  },
164  "px_4":{
165    "paddingHorizontal":12
166  },
167  "py_4":{
168    "paddingVertical":12
169  },
170  "m_5":{
171    "margin":15
172  },
173  "mt_5":{
174    "marginTop":15
175  },
176  "mb_5":{
177    "marginBottom":15
178  },
179  "ml_5":{
180    "marginLeft":15
181  },
182  "mr_5":{
183    "marginRight":15
184  },
185  "mx_5":{
186    "marginHorizontal":15
187  },
188  "my_5":{
189    "marginVertical":15
190  },
191  "p_5":{
192    "padding":15
193  },
194  "pt_5":{
195    "paddingTop":15
196  },
197  "pb_5":{
198    "paddingBottom":15
199  },
200  "pl_5":{
201    "paddingLeft":15
202  },
203  "pr_5":{
204    "paddingRight":15
205  },
206  "px_5":{
207    "paddingHorizontal":15
208  },
209  "py_5":{
210    "paddingVertical":15
211  },
212  "m_6":{
213    "margin":18
214  },
215  "mt_6":{
216    "marginTop":18
217  },
218  "mb_6":{
219    "marginBottom":18
220  },
221  "ml_6":{
222    "marginLeft":18
223  },
224  "mr_6":{
225    "marginRight":18
226  },
227  "mx_6":{
228    "marginHorizontal":18
229  },
230  "my_6":{
231    "marginVertical":18
232  },
233  "p_6":{
234    "padding":18
235  },
236  "pt_6":{
237    "paddingTop":18
238  },
239  "pb_6":{
240    "paddingBottom":18
241  },
242  "pl_6":{
243    "paddingLeft":18
244  },
245  "pr_6":{
246    "paddingRight":18
247  },
248  "px_6":{
249    "paddingHorizontal":18
250  },
251  "py_6":{
252    "paddingVertical":18
253  },
254  "m_7":{
255    "margin":21
256  },
257  "mt_7":{
258    "marginTop":21
259  },
260  "mb_7":{
261    "marginBottom":21
262  },
263  "ml_7":{
264    "marginLeft":21
265  },
266  "mr_7":{
267    "marginRight":21
268  },
269  "mx_7":{
270    "marginHorizontal":21
271  },
272  "my_7":{
273    "marginVertical":21
274  },
275  "p_7":{
276    "padding":21
277  },
278  "pt_7":{
279    "paddingTop":21
280  },
281  "pb_7":{
282    "paddingBottom":21
283  },
284  "pl_7":{
285    "paddingLeft":21
286  },
287  "pr_7":{
288    "paddingRight":21
289  },
290  "px_7":{
291    "paddingHorizontal":21
292  },
293  "py_7":{
294    "paddingVertical":21
295  },
296  "m_8":{
297    "margin":24
298  },
299  "mt_8":{
300    "marginTop":24
301  },
302  "mb_8":{
303    "marginBottom":24
304  },
305  "ml_8":{
306    "marginLeft":24
307  },
308  "mr_8":{
309    "marginRight":24
310  },
311  "mx_8":{
312    "marginHorizontal":24
313  },
314  "my_8":{
315    "marginVertical":24
316  },
317  "p_8":{
318    "padding":24
319  },
320  "pt_8":{
321    "paddingTop":24
322  },
323  "pb_8":{
324    "paddingBottom":24
325  },
326  "pl_8":{
327    "paddingLeft":24
328  },
329  "pr_8":{
330    "paddingRight":24
331  },
332  "px_8":{
333    "paddingHorizontal":24
334  },
335  "py_8":{
336    "paddingVertical":24
337  },
338  "m_9":{
339    "margin":27
340  },
341  "mt_9":{
342    "marginTop":27
343  },
344  "mb_9":{
345    "marginBottom":27
346  },
347  "ml_9":{
348    "marginLeft":27
349  },
350  "mr_9":{
351    "marginRight":27
352  },
353  "mx_9":{
354    "marginHorizontal":27
355  },
356  "my_9":{
357    "marginVertical":27
358  },
359  "p_9":{
360    "padding":27
361  },
362  "pt_9":{
363    "paddingTop":27
364  },
365  "pb_9":{
366    "paddingBottom":27
367  },
368  "pl_9":{
369    "paddingLeft":27
370  },
371  "pr_9":{
372    "paddingRight":27
373  },
374  "px_9":{
375    "paddingHorizontal":27
376  },
377  "py_9":{
378    "paddingVertical":27
379  }
380}