7
7
[ ![ Twitter] ( https://img.shields.io/twitter/url/https/github.com/renatorib/react-sizes.svg?style=social&style=flat-square )] ( https://twitter.com/intent/tweet?url=https://github.com/renatorib/react-sizes )
8
8
9
9
## Install
10
+
10
11
```
11
12
yarn add react-sizes
12
13
```
14
+
13
15
```
14
16
npm install react-sizes
15
17
```
16
18
17
19
## What and why
20
+
18
21
React Sizes is a high-order component with a high performance that transform window sizes (width and height) into props.
19
22
You can check inside your component, for example, if user's window is less than 480 pixels of width, and add a custom
20
23
content.
21
24
22
25
It can be very powerful for when you need to display different content for mobile and desktop.
23
- But it's not limited to this case. Just use that at your needs.
26
+ But it's not limited to this case. Just use that at your needs.
24
27
25
28
## Usage
26
29
27
30
#### With class component.
31
+
28
32
``` jsx
29
- import React , { Component } from ' react' ;
30
- import withSizes from ' react-sizes' ;
33
+ import React , { Component } from ' react'
34
+ import withSizes from ' react-sizes'
31
35
32
36
class MyComponent extends Component {
33
37
render () {
34
- return (
35
- < div> {this .props .isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
36
- );
38
+ return < div> {this .props .isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
37
39
}
38
40
}
39
41
40
42
const mapSizesToProps = ({ width }) => ({
41
43
isMobile: width < 480 ,
42
- });
44
+ })
43
45
44
- export default withSizes (mapSizesToProps)(MyComponent);
46
+ export default withSizes (mapSizesToProps)(MyComponent)
45
47
```
48
+
46
49
You can play with this example [ here] ( https://codesandbox.io/s/Rg0DDOWnE ) .
47
50
48
51
#### As decorator.
52
+
49
53
``` jsx
50
- import React from ' react' ;
51
- import withSizes from ' react-sizes' ;
54
+ import React from ' react'
55
+ import withSizes from ' react-sizes'
52
56
53
57
@withSizes (({ width }) => ({ isMobile: width < 480 }))
54
58
class MyComponent extends Component {
55
59
render () {
56
- return (
57
- < div> {this .props .isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
58
- );
60
+ return < div> {this .props .isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
59
61
}
60
62
}
61
63
62
- export default MyComponent ;
64
+ export default MyComponent
63
65
```
64
66
65
67
#### Interoperate with other libraries.
68
+
66
69
``` jsx
67
- import React from ' react' ;
68
- import withSizes from ' react-sizes' ;
69
- import { withState , compose } from ' recompose' ;
70
+ import React from ' react'
71
+ import withSizes from ' react-sizes'
72
+ import { withState , compose } from ' recompose'
70
73
71
74
const enhancer = compose (
72
75
withState (' counter' , ' setCounter' , 0 ),
73
- withSizes (({ width }) => ({ isMobile: width < 480 })),
74
- );
76
+ withSizes (({ width }) => ({ isMobile: width < 480 }))
77
+ )
75
78
76
79
const MyComponent = enhancer (({ isMobile, counter, setCounter }) => (
77
80
< div>
78
81
< div>
79
- Count: {counter} < button onClick= {() => setCounter (n => n + 1 )}> Increment< / button>
82
+ Count: {counter}{' ' }
83
+ < button onClick= {() => setCounter (n => n + 1 )}> Increment< / button>
80
84
< / div>
81
85
< div> {isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
82
86
< / div>
83
- ));
87
+ ))
84
88
85
- export default MyComponent ;
89
+ export default MyComponent
86
90
```
87
91
88
92
#### With functional component.
93
+
89
94
``` jsx
90
- import React from ' react' ;
91
- import withSizes from ' react-sizes' ;
95
+ import React from ' react'
96
+ import withSizes from ' react-sizes'
92
97
93
98
const MyComponent = ({ isMobile }) => (
94
99
< div> {isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
95
- );
100
+ )
96
101
97
102
const mapSizesToProps = ({ width }) => ({
98
103
isMobile: width < 480 ,
99
- });
104
+ })
100
105
101
- export default withSizes (mapSizesToProps)(MyComponent);
106
+ export default withSizes (mapSizesToProps)(MyComponent)
102
107
```
103
108
104
109
#### Mess with props.
110
+
105
111
(Added in 0.1.0)
112
+
106
113
``` jsx
107
- import React from ' react' ;
108
- import withSizes from ' react-sizes' ;
114
+ import React from ' react'
115
+ import withSizes from ' react-sizes'
109
116
110
117
const MyComponent = ({ isMobile }) => (
111
118
< div> {isMobile ? ' Is Mobile' : ' Is Not Mobile' }< / div>
112
- );
119
+ )
113
120
114
121
const mapSizesToProps = ({ width }, { mobileBreakpoint }) => ({
115
122
isMobile: width < mobileBreakpoint,
116
- });
123
+ })
117
124
118
- export default withSizes (mapSizesToProps)(MyComponent);
125
+ export default withSizes (mapSizesToProps)(MyComponent)
119
126
```
127
+
120
128
then:
129
+
121
130
``` jsx
122
131
< MyComponent mobileBreakpoint= {480 } / >
123
132
< MyComponent mobileBreakpoint= {400 } / >
124
133
< MyComponent mobileBreakpoint= {600 } / >
125
134
```
126
135
127
136
#### With presets selectors.
137
+
128
138
``` diff
129
139
- const mapSizesToProps = ({ width }) => ({
130
140
- isMobile: width < 480,
@@ -138,69 +148,145 @@ then:
138
148
## Presets Selectors
139
149
140
150
You can check all ** our** presets selectors at our main code ` src/withSizes.js ` .
151
+
141
152
``` js
142
- withSizes .isMobile = ({ width }) => width < 480 ;
143
- withSizes .isTablet = ({ width }) => width >= 480 && width < 1024 ;
144
- withSizes .isDesktop = ({ width }) => width >= 1024 ;
153
+ withSizes .isMobile = ({ width }) => width < 480
154
+ withSizes .isTablet = ({ width }) => width >= 480 && width < 1024
155
+ withSizes .isDesktop = ({ width }) => width >= 1024
145
156
146
- withSizes .isGtMobile = ( sizes ) => ! withSizes .isMobile (sizes);
147
- withSizes .isGtTablet = ( sizes ) => withSizes .isDesktop (sizes);
157
+ withSizes .isGtMobile = sizes => ! withSizes .isMobile (sizes)
158
+ withSizes .isGtTablet = sizes => withSizes .isDesktop (sizes)
148
159
149
- withSizes .isStTablet = ( sizes ) => withSizes .isMobile (sizes);
150
- withSizes .isStDesktop = ( sizes ) => ! withSizes .isStDesktop (sizes);
160
+ withSizes .isStTablet = sizes => withSizes .isMobile (sizes)
161
+ withSizes .isStDesktop = sizes => ! withSizes .isStDesktop (sizes)
151
162
152
- withSizes .isTabletAndGreater = ( sizes ) => ! withSizes .isMobile (sizes);
153
- withSizes .isTabletAndSmaller = ( sizes ) => ! withSizes .isStDesktop (sizes);
163
+ withSizes .isTabletAndGreater = sizes => ! withSizes .isMobile (sizes)
164
+ withSizes .isTabletAndSmaller = sizes => ! withSizes .isStDesktop (sizes)
154
165
```
155
166
156
167
If it don't fit to your needs, you can create your own selectors.
168
+
157
169
``` jsx
158
170
// utils/sizes/selectors.js
159
- export const isntDesktop = ({ width }) => width < 1024 ;
160
- export const backgroundColor = ({ width }) => width < 480 ? ' red' : ' green' ;
171
+ export const isntDesktop = ({ width }) => width < 1024
172
+ export const backgroundColor = ({ width }) => ( width < 480 ? ' red' : ' green' )
161
173
162
174
// your component
163
- import { isntDesktop , backgroundColor } from ' utils/sizes/selectors' ;
175
+ import { isntDesktop , backgroundColor } from ' utils/sizes/selectors'
164
176
165
177
const mapSizesToProps = sizes => ({
166
178
canDisplayMobileFeature: isntDesktop (sizes),
167
179
backgroundColor: backgroundColor (sizes),
168
- });
180
+ })
169
181
```
182
+
170
183
> ` sizes ` argument is an object with ` width ` and ` height ` properties and represents DOM window width and height.
171
184
172
185
## Guide
173
186
174
187
#### mapSizesToProps(sizes)
188
+
175
189
` sizes ` argument is an object with ` width ` and ` height ` of DOM window.
176
190
177
191
``` js
178
192
const mapSizesToProps = sizes => {
179
193
console .log (sizes) // { width: 1200, height: 720 } (example)
180
- };
194
+ }
181
195
```
182
196
183
- In pratice, it is a callback that return props that will injected into your Component.
197
+ In pratice, it is a callback that return props that will injected into your Component.
198
+
184
199
``` js
185
200
const mapSizesToProps = function (sizes ) {
186
201
const props = {
187
202
backgroundColor: sizes .width < 700 ? ' red' : ' green' ,
188
- };
203
+ }
189
204
190
- return props;
191
- };
205
+ return props
206
+ }
192
207
```
193
208
194
209
But you can simplify this to stay practical and elegant.
210
+
195
211
``` js
196
212
const mapSizesToProps = ({ width }) => ({
197
213
backgroundColor: width < 700 ? ' red' : ' green' ,
198
- });
214
+ })
215
+ ```
216
+
217
+ ## Server Side Rendering
218
+
219
+ Since React Sizes rely on window to computate sizes, we can't computate the values in server enviroment. To try to get around this we can ** guess** user viewport based on your user-agent, and pass values by a Context Provider.
220
+ But be careful, ** user-agent based detection is not a reliable solution** . It's a workaround.
221
+
222
+ ``` js
223
+ // Config can be created based on user-agent. See below
224
+ const config = { fallbackWidth: 360 , fallbackHeight: 640 }
225
+
226
+ return (
227
+ < SizesProvider config= {config}>
228
+ < App / >
229
+ < / SizesProvider>
230
+ )
231
+ ```
232
+
233
+ Example:
234
+
235
+ ``` js
236
+ import MobileDetect from ' mobile-detect'
237
+ import Express from ' express'
238
+ import { SizesProvider } from ' react-sizes'
239
+ // All other imports
240
+
241
+ const getSizesFallback = userAgent => {
242
+ const md = new MobileDetect (userAgent)
243
+
244
+ if (!! md .mobile ()) {
245
+ return {
246
+ fallbackWidth: 360 ,
247
+ fallbackHeight: 640 ,
248
+ }
249
+ } else if (!! md .tablet ()) {
250
+ return {
251
+ fallbackWidth: 768 ,
252
+ fallbackHeight: 1024 ,
253
+ }
254
+ }
255
+
256
+ return {
257
+ fallbackWidth: 1280 ,
258
+ fallbackHeiht: 700 ,
259
+ }
260
+ }
261
+
262
+ // Note: you don't need to use express, this is just an example
263
+ const app = new Express ()
264
+ app .use ((req , res ) => {
265
+ // ...
266
+ const sizesConfig = getSizesFallback (req .headers [' user-agent' ])
267
+
268
+ const App = (
269
+ < AnotherProvider>
270
+ < Router location= {req .url }>
271
+ < SizesProvider config= {sizesConfig}>
272
+ < Root / >
273
+ < / SizesProvider>
274
+ < / Router>
275
+ < / AnotherProvider>
276
+ )
277
+
278
+ res .status (200 )
279
+ res .send (` <!doctype html>\n ${ ReactDOM .renderToString (< App / > )} ` )
280
+ res .end ()
281
+ })
282
+
283
+ app .listen (/* ... */ )
199
284
```
200
285
201
286
## Performance Notes
202
287
203
288
#### Shallow Compare
289
+
204
290
React Sizes do a shallow compare in props generated from ` mapSizesToProps ` (called ` propsToPass ` ), so it will only rerender when they really change. If you create a deep data sctructure, this can generate false positives. In these cases, we recommend using immutable for a more reliable shallow compare result. Or just don't use deep data structures, if possible.
205
291
206
292
## Contribute
0 commit comments