Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 9cda1b1

Browse files
stephan-noelSoaresMG
authored andcommitted
chore: refactor ResponsiveProvider
1 parent da38086 commit 9cda1b1

File tree

8 files changed

+211
-176
lines changed

8 files changed

+211
-176
lines changed

.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"eslint:recommended",
1111
"plugin:prettier/recommended",
1212
"plugin:react/recommended",
13+
"plugin:react-hooks/recommended",
1314
"prettier/react"
1415
],
1516
"parser": "babel-eslint",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"eslint-plugin-babel": "^5.3.0",
7171
"eslint-plugin-prettier": "^3.1.3",
7272
"eslint-plugin-react": "^7.19.0",
73+
"eslint-plugin-react-hooks": "^4.0.8",
7374
"eslint-plugin-sort-imports-es6-autofix": "^0.5.0",
7475
"husky": "^2.4.0",
7576
"jest": "^24.8.0",

src/ResponsiveProvider.js

Lines changed: 0 additions & 176 deletions
This file was deleted.

src/ResponsiveProvider/index.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { getBreakpoints, getMediaqueries, getQueriesObjects } from '../utils';
2+
import PropTypes from 'prop-types';
3+
import React, { useMemo, useRef } from 'react';
4+
import ResponsiveContext from '../ResponsiveContext';
5+
import useDebugResponsive from './useDebugResponsive';
6+
import useMediaType from './useMediaType';
7+
import useOrientation from './useOrientation';
8+
9+
const ResponsiveProvider = ({
10+
initialMediaType,
11+
defaultOrientation,
12+
children,
13+
breakpoints,
14+
breakpointsMax,
15+
mediaQueries,
16+
}) => {
17+
const breakpointsWithInitialValue = {
18+
_initial: '0em',
19+
...breakpoints,
20+
};
21+
22+
const breakpointNames = Object.keys(
23+
mediaQueries || breakpointsWithInitialValue
24+
);
25+
26+
if (!mediaQueries) {
27+
mediaQueries = getMediaqueries(
28+
breakpointsWithInitialValue,
29+
breakpointsMax,
30+
breakpointNames
31+
);
32+
}
33+
34+
const breakpointsRef = useRef(
35+
getBreakpoints(mediaQueries, breakpointNames)
36+
);
37+
38+
const { currentMediaType, isCalculated } = useMediaType(
39+
breakpointsRef,
40+
initialMediaType
41+
);
42+
43+
const queriesObjects = useMemo(
44+
() => getQueriesObjects(currentMediaType, breakpointsRef.current),
45+
[currentMediaType, breakpointsRef]
46+
);
47+
48+
const currentOrientation = useOrientation(defaultOrientation);
49+
50+
const contextObject = useMemo(
51+
() => ({
52+
mediaType: currentMediaType,
53+
orientation: currentOrientation,
54+
isCalculated,
55+
...queriesObjects,
56+
}),
57+
[currentMediaType, currentOrientation, isCalculated, queriesObjects]
58+
);
59+
60+
useDebugResponsive(contextObject, currentMediaType);
61+
62+
return (
63+
<ResponsiveContext.Provider value={contextObject}>
64+
{children}
65+
</ResponsiveContext.Provider>
66+
);
67+
};
68+
69+
const breakpointsPropTypes = {
70+
xs: PropTypes.string,
71+
sm: PropTypes.string,
72+
md: PropTypes.string,
73+
lg: PropTypes.string,
74+
xl: PropTypes.string,
75+
};
76+
77+
ResponsiveProvider.defaultProps = {
78+
initialMediaType: 'xs',
79+
defaultOrientation: null,
80+
};
81+
82+
ResponsiveProvider.propTypes = {
83+
initialMediaType: PropTypes.oneOf([
84+
'_initial',
85+
'xs',
86+
'sm',
87+
'md',
88+
'lg',
89+
'xl',
90+
]),
91+
defaultOrientation: PropTypes.oneOf(['landscape', 'portrait']),
92+
children: PropTypes.oneOfType([
93+
PropTypes.arrayOf(PropTypes.node),
94+
PropTypes.node,
95+
]).isRequired,
96+
breakpoints: PropTypes.exact(breakpointsPropTypes),
97+
breakpointsMax: PropTypes.exact(breakpointsPropTypes),
98+
mediaQueries: PropTypes.exact({
99+
...breakpointsPropTypes,
100+
_initial: PropTypes.string,
101+
}),
102+
};
103+
104+
export default ResponsiveProvider;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { useEffect } from 'react';
2+
3+
const useDebugResponsive = (contextObject, currentMediaType) => {
4+
useEffect(() => {
5+
if (process && process.env && process.env.NODE_ENV === 'development') {
6+
/* eslint-disable no-console */
7+
console.group(
8+
'%c @farfetch/react-context-responsive updated!',
9+
'color:#c4aa84; font-weight:bold;'
10+
);
11+
console.log(
12+
'%c Current media type:',
13+
'font-weight:bold;',
14+
currentMediaType
15+
);
16+
console.log('%c Context:', 'font-weight:bold;', contextObject);
17+
console.groupEnd();
18+
/* eslint-enable no-console */
19+
}
20+
}, [contextObject, currentMediaType]);
21+
};
22+
23+
export default useDebugResponsive;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useEffect, useState } from 'react';
2+
3+
const useMediaType = (breakpointsRef, initialMediaType) => {
4+
const [isCalculated, setIsCalculated] = useState(false);
5+
const [currentMediaType, setCurrentMediaType] = useState(initialMediaType);
6+
7+
useEffect(() => {
8+
const breakpoints = breakpointsRef.current;
9+
const localMediaQueries = breakpoints.map(
10+
(breakpoint) => breakpoint.mediaQuery
11+
);
12+
const mediaQueryListsAndListeners = localMediaQueries.map(
13+
(mediaQuery, index) => {
14+
const mediaQueryList = window.matchMedia(mediaQuery);
15+
16+
if (mediaQueryList.matches) {
17+
setCurrentMediaType(breakpoints[index].mediaType);
18+
setIsCalculated(true);
19+
}
20+
21+
const listener = (event) => {
22+
event.matches &&
23+
setCurrentMediaType(breakpoints[index].mediaType);
24+
};
25+
26+
mediaQueryList.addListener(listener);
27+
28+
return [mediaQueryList, listener];
29+
}
30+
);
31+
32+
return () => {
33+
mediaQueryListsAndListeners.forEach(
34+
([mediaQueryList, listener]) => {
35+
mediaQueryList.removeListener(listener);
36+
}
37+
);
38+
};
39+
}, [breakpointsRef]);
40+
41+
return { isCalculated, currentMediaType };
42+
};
43+
44+
export default useMediaType;

0 commit comments

Comments
 (0)