diff --git a/README.md b/README.md
index 1ac9967..50cf542 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
[](https://circleci.com/gh/wcandillon/react-native-responsive-ui)
[](https://badge.fury.io/js/react-native-responsive-ui)
-
Building responsive UIs in React Native.

@@ -58,102 +57,66 @@ export default class Login extends Component {
| platform | string | Platform of the device. See [Platform](https://facebook.github.io/react-native/docs/platform-specific-code.html#platform-module). |
| condition | boolean | Abritrary boolean value that must be true for the media query to pass. |
-
-### useDimensions
+### useStyle
```jsx
import React from "react";
-import {useDimensions} from "react-native-responsive-ui";
+import {useStyle} from "react-native-responsive-ui";
export default ({ children }) => {
- const {width, height} = useDimensions();
- console.log(`New window dimensions: ${width}x${height}`);
- return children;
-};
-```
-
-### useStylesheet
-
-```jsx
-import React from "react";
-import {useStylesheet} from "react-native-responsive-ui";
-
-export default class Buttons extends ResponsiveComponent {
- render() {
- const style = useStylesheet(staticStyle)
- return
-
-
- ;
+ const styles = useStyle(cond => ({
+ container: {
+ flex: 1,
+ cond(
+ { orientation: "landscape" },
+ { flexDirection: "row" }
+ ),
+ cond(
+ { orientation: "portrait" },
+ { flexDirection: "column" }
+ ),
}
-}
-
-const staticStyle = [
- {
- query: { orientation: "landscape" },
- style: {
- btns: {
- flexDirection: "row"
- },
- btn: {
- flex: 1
- }
- }
- },
- {
- query: { orientation: "portrait" },
- style: {
- btns: {
- alignSelf: "stretch"
- },
- btn: {
- flex: 0
- }
- }
- }
-];
-```
-
-### Media Query
+ }));
-`mediaQuery()` evaluates a media query and return true or false.
-See example below.
-
-```jsx
-import {mediaQuery, useDimensions} from "react-native-responsive-ui";
-
-const {width, height} = useDimensions();
-mediaQuery({ orientation: "portrait", minHeight: 450 }, width, height)
+ return ;
+};
```
-### ResponsiveComponent
+or without hooks:
-`ResponsiveComponents` extends `React.Component` and add the window dimensions to the state of the component.
```jsx
import React from "react";
-import {ResponsiveComponent} from "react-native-responsive-ui";
+import {getStyle} from "react-native-responsive-ui";
-export default class Debug extends ResponsiveComponent {
- render() {
- const {width, height} = this.state.window;
- console.log(`New window dimensions: ${width}x${height}`);
- return null;
+export default ({ children }) => {
+ const styles = getStyle(dimensions.get("window"), cond => ({
+ container: {
+ flex: 1,
+ ...cond(
+ { orientation: "landscape" },
+ { flexDirection: "row" }
+ ),
+ ...cond(
+ { orientation: "portrait" },
+ { flexDirection: "column" }
+ ),
}
-}
+ }));
+
+ return ;
+};
```
-### getStyleSheet
+### useDimensions
```jsx
import React from "react";
-import {ResponsiveComponent, getStyleSheet} from "react-native-responsive-ui";
+import {useDimensions} from "react-native-responsive-ui";
-export default class Debug extends ResponsiveComponent {
- render() {
- const {width, height} = this.state.window;
- const style = getStyleSheet({width, height})
- return
- }
-}
+export default ({ children }) => {
+ const {width, height} = useDimensions();
+ console.log(`New window dimensions: ${width}x${height}`);
+ return children;
+};
```
\ No newline at end of file
diff --git a/package.json b/package.json
index 9044859..66c8b3d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-responsive-ui",
- "version": "2.1.1",
+ "version": "3.0.0",
"description": "Responsive UIs for React Native",
"main": "dist/src/index.js",
"repository": "https://github.com/wcandillon/react-native-responsive-ui",
diff --git a/src/DimensionsContext.tsx b/src/DimensionsContext.tsx
new file mode 100644
index 0000000..79a2d0e
--- /dev/null
+++ b/src/DimensionsContext.tsx
@@ -0,0 +1,21 @@
+import React from "react";
+import { Dimensions } from "react-native";
+
+import useDimensions from "./useDimensions";
+
+export const DimensionsContext = React.createContext(Dimensions.get("window"));
+
+interface DimensionProviderProps {
+ children: React.ReactNode;
+}
+
+export const DimensionsConsumer = DimensionsContext.Consumer;
+
+export const DimensionsProvider = ({ children }: DimensionProviderProps) => {
+ const dimensions = useDimensions();
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/MediaQuery.tsx b/src/MediaQuery.tsx
index 0cc384f..188d416 100644
--- a/src/MediaQuery.tsx
+++ b/src/MediaQuery.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { PixelRatio, Platform } from "react-native";
+import { PixelRatio, Platform, ScaledSize } from "react-native";
import useDimensions from "./useDimensions";
type Orientation = "landscape" | "portrait";
@@ -26,6 +26,7 @@ export const isInInterval = (
(min === undefined || value >= min) && (max === undefined || value <= max);
export const mediaQuery = (
+ dimensions: ScaledSize,
{
minWidth,
maxWidth,
@@ -38,10 +39,9 @@ export const mediaQuery = (
minPixelRatio,
maxPixelRatio,
condition
- }: IMediaQuery,
- width: number,
- height: number
+ }: IMediaQuery
): boolean => {
+ const { width, height } = dimensions;
const currentOrientation: Orientation =
width > height ? "landscape" : "portrait";
return (
@@ -60,8 +60,8 @@ interface MediaQueryProps extends IMediaQuery {
}
export default ({ children, ...props }: MediaQueryProps) => {
- const { width, height } = useDimensions();
- const val = mediaQuery(props, width, height);
+ const dimensions = useDimensions();
+ const val = mediaQuery(dimensions, props);
if (val) {
return children;
}
diff --git a/src/ResponsiveComponent.tsx b/src/ResponsiveComponent.tsx
deleted file mode 100644
index 02df2f1..0000000
--- a/src/ResponsiveComponent.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Component } from "react";
-import { Dimensions, ScaledSize } from "react-native";
-
-interface ResponsiveComponentProps {}
-
-interface ResponsiveComponentState {
- window: ScaledSize;
-}
-
-export default abstract class ResponsiveComponent extends Component<
- ResponsiveComponentProps,
- ResponsiveComponentState
-> {
- state = {
- // eslint-disable-next-line react/no-unused-state
- window: Dimensions.get("window")
- };
-
- componentWillMount() {
- Dimensions.addEventListener("change", this.onDimensionChange);
- }
-
- componentWillUnmount() {
- Dimensions.removeEventListener("change", this.onDimensionChange);
- }
-
- onDimensionChange = (dims: ResponsiveComponentState) => this.setState(dims);
-}
diff --git a/src/index.ts b/src/index.ts
index 22e2829..5634f90 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,8 @@
-export { default as useDimensions } from "./useDimensions";
-export { useStylesheet, getStylesheet } from "./useStylesheet";
export { default as MediaQuery, IMediaQuery, mediaQuery } from "./MediaQuery";
-export { default as ResponsiveComponent } from "./ResponsiveComponent";
+export {
+ DimensionsContext,
+ DimensionsProvider,
+ DimensionsConsumer
+} from "./DimensionsContext";
+export { default as useDimensions } from "./useDimensions";
+export { getStyle, useStyle } from "./useStyle";
diff --git a/src/useDimensions.ts b/src/useDimensions.tsx
similarity index 71%
rename from src/useDimensions.ts
rename to src/useDimensions.tsx
index 303c979..37295e8 100644
--- a/src/useDimensions.ts
+++ b/src/useDimensions.tsx
@@ -6,11 +6,8 @@ const dims = Dimensions.get("window");
export default () => {
const [dimensions, setDimensions] = useState(dims);
- const onChange = ({
- window: { width, height, scale, fontScale }
- }: {
- window: ScaledSize;
- }) => setDimensions({ width, height, scale, fontScale });
+ const onChange = ({ window }: { window: ScaledSize }) =>
+ setDimensions(window);
useEffect(() => {
Dimensions.addEventListener("change", onChange);
diff --git a/src/useStyle.ts b/src/useStyle.ts
new file mode 100644
index 0000000..e013c09
--- /dev/null
+++ b/src/useStyle.ts
@@ -0,0 +1,39 @@
+import { ScaledSize, ViewStyle, TextStyle, ImageStyle } from "react-native";
+import { mediaQuery, IMediaQuery } from "./MediaQuery";
+import useDimensions from "./useDimensions";
+
+type Style = ViewStyle | TextStyle | ImageStyle;
+
+let id = 0;
+const uniqueId = () => {
+ id += 1;
+ return id;
+};
+
+type ReponsiveStyles = Style & {
+ [condition: string]: Style;
+};
+
+const selectStyle = (styles: ReponsiveStyles): Style => ({
+ ...(Object.keys(styles)
+ .filter(style => style.endsWith("-true"))
+ .map(style => styles[style]) as Style)
+});
+
+export const useStyle = (
+ styles: (cond: (query: IMediaQuery) => string) => ReponsiveStyles
+): Style => {
+ const dimensions = useDimensions();
+ const cond = (query: IMediaQuery) =>
+ `${uniqueId()}-${mediaQuery(dimensions, query)}`;
+ return selectStyle(styles(cond));
+};
+
+export const getStyle = (
+ dimensions: ScaledSize,
+ styles: (cond: (query: IMediaQuery) => string) => ReponsiveStyles
+): Style => {
+ const cond = (query: IMediaQuery) =>
+ `${uniqueId()}-${mediaQuery(dimensions, query)}`;
+ return selectStyle(styles(cond));
+};
diff --git a/src/useStylesheet.ts b/src/useStylesheet.ts
deleted file mode 100644
index 780e39c..0000000
--- a/src/useStylesheet.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-// @flow
-import * as _ from "lodash";
-import { ViewStyle, TextStyle, ImageStyle } from "react-native";
-import { mediaQuery, IMediaQuery } from "./MediaQuery";
-import useDimensions from "./useDimensions";
-
-type NamedStyles = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle };
-type MediaQueryStyle = {
- query: IMediaQuery;
- style: NamedStyles;
-};
-
-export const getStylesheet = (
- { width, height }: { width: number; height: number },
- styles: MediaQueryStyle[]
-) => {
- const selectedStyles: NamedStyles[] = [];
- styles.forEach(style =>
- mediaQuery(style.query, width, height)
- ? selectedStyles.push(style.style)
- : undefined
- );
- return _.merge.apply[], NamedStyles>(
- null,
- selectedStyles
- );
-};
-
-export const useStylesheet = (styles: MediaQueryStyle[]) => {
- const dimensions = useDimensions();
- return getStylesheet(dimensions, styles);
-};