{"id":18836025,"url":"https://github.com/wkovacs64/react-native-responsive-image-view","last_synced_at":"2025-05-15T06:08:17.184Z","repository":{"id":37954622,"uuid":"113911575","full_name":"wKovacs64/react-native-responsive-image-view","owner":"wKovacs64","description":"React Native component for scaling an Image within the parent View","archived":false,"fork":false,"pushed_at":"2025-05-15T05:40:56.000Z","size":18102,"stargazers_count":389,"open_issues_count":1,"forks_count":11,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-15T06:07:31.988Z","etag":null,"topics":["image","react","react-native","react-native-component","responsive-images","view"],"latest_commit_sha":null,"homepage":"https://snack.expo.dev/@wkovacs64/responsiveimageview","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wKovacs64.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG-1.x.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"wKovacs64"}},"created_at":"2017-12-11T21:41:45.000Z","updated_at":"2025-05-15T05:40:58.000Z","dependencies_parsed_at":"2024-01-20T21:29:58.015Z","dependency_job_id":"a148af6e-ee1d-4152-b5e1-40b1390b60bd","html_url":"https://github.com/wKovacs64/react-native-responsive-image-view","commit_stats":{"total_commits":1654,"total_committers":5,"mean_commits":330.8,"dds":"0.47339782345828296","last_synced_commit":"b1c8d87dbe3c102dade47778708ddd2ea1dffb3e"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wKovacs64%2Freact-native-responsive-image-view","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wKovacs64%2Freact-native-responsive-image-view/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wKovacs64%2Freact-native-responsive-image-view/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wKovacs64%2Freact-native-responsive-image-view/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wKovacs64","download_url":"https://codeload.github.com/wKovacs64/react-native-responsive-image-view/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254283350,"owners_count":22045141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image","react","react-native","react-native-component","responsive-images","view"],"created_at":"2024-11-08T02:17:58.514Z","updated_at":"2025-05-15T06:08:17.164Z","avatar_url":"https://github.com/wKovacs64.png","language":"TypeScript","funding_links":["https://github.com/sponsors/wKovacs64"],"categories":[],"sub_categories":[],"readme":"# react-native-responsive-image-view\n\n_React Native component for scaling an `Image` within the parent `View`_\n\n[![npm Version][npm-image]][npm-url] [![Build Status][ci-image]][ci-url]\n[![Code Coverage][coverage-image]][coverage-url]\n\n## The problem\n\nYou want to display an image in your React Native app that fills the width of its container and\nscales its height according to the aspect ratio of the image. If you're coming from front-end web\ndevelopment, you may be familiar with Bootstrap 3's `img-responsive` class or manually applying\n`max-width: 100%` and `height: auto` to an image. Unfortunately, `auto` is not a valid value for\n`height` in React Native, so that technique doesn't quite translate.\n\n## This solution\n\nThis calculates the aspect ratio of your image for you (or uses a fixed value, if you supply one)\nand provides you with the appropriate props to apply to a `View` container and an `Image` inside it\nwhich will produce the results you're looking for. The secret sauce is setting both the `height` and\n`width` attributes of the `style` prop on the `Image` to `100%` and wrapping it with a `View` that\nhas its [`aspectRatio`][aspectratio] style property set to match the aspect ratio you want. The\npackage provides both a [render prop component][render-props] and a [custom hook][custom-hooks].\n\n## Table of Contents\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Component](#component)\n  - [Hook](#hook)\n- [Input](#input)\n  - [Basic Inputs](#basic-inputs)\n    - [onLoad](#onload)\n    - [onError](#onerror)\n    - [source](#source)\n  - [Advanced Inputs](#advanced-inputs)\n    - [aspectRatio](#aspectratio)\n  - [Component-only Inputs](#component-only-inputs)\n    - [Render Prop Function](#render-prop-function)\n      - [component](#component)\n      - [render](#render)\n      - [children](#children)\n- [Output](#output)\n  - [prop getters](#prop-getters)\n    - [`getViewProps`](#getviewprops)\n    - [`getImageProps`](#getimageprops)\n  - [state](#state)\n  - [utils](#utils)\n- [Examples](#examples)\n- [Snack Playground](#snack-playground)\n- [Inspiration](#inspiration)\n- [Other Solutions](#other-solutions)\n- [LICENSE](#license)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Installation\n\nUsing [npm][npm]:\n\n```shell\nnpm install react-native-responsive-image-view\n```\n\n\u003e This package also depends on `react` and `react-native`. Please make sure you have those installed\n\u003e as well.\n\n## Usage\n\nAs mentioned above, this package includes both a render prop component (the default export) and a\ncustom hook (a named export). They provide the same functionality, so choose whichever is most\nappropriate for your project.\n\n### Component\n\n```tsx\nimport * as React from 'react';\nimport { Image, View } from 'react-native';\nimport { ResponsiveImageView } from 'react-native-responsive-image-view';\n\nfunction MyComponent({ imageUri }) {\n  return (\n    \u003cResponsiveImageView source={{ uri: imageUri }}\u003e\n      {({ getViewProps, getImageProps }) =\u003e (\n        \u003cView {...getViewProps()}\u003e\n          \u003cImage {...getImageProps()} /\u003e\n        \u003c/View\u003e\n      )}\n    \u003c/ResponsiveImageView\u003e\n  );\n}\n```\n\n**N.B.** This component doesn't render anything itself, it just calls your render function or\ninjected component and renders that. [\"Use a render prop!\"][use-a-render-prop] Just be sure to\nrender the `Image` inside the `View` in your `render` function.\n\n\u003e In addition to a literal `render` prop, it also supports the component injection and\n\u003e function-as-children patterns if you prefer. See the [Render Prop Function](#render-prop-function)\n\u003e section for details.\n\n### Hook\n\n```tsx\nimport * as React from 'react';\nimport { Image, View } from 'react-native';\nimport { useResponsiveImageView } from 'react-native-responsive-image-view';\n\nfunction MyComponent({ imageUri }) {\n  const { getViewProps, getImageProps } = useResponsiveImageView({ source: { uri: imageUri } });\n\n  return (\n    \u003cView {...getViewProps()}\u003e\n      \u003cImage {...getImageProps()} /\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n## Input\n\nThe component takes its inputs as individual props, while the hook takes its inputs as an object\n(the only parameter), but the inputs themselves are primarily the same:\n\n### Basic Inputs\n\n#### onLoad\n\n\u003e `function()` | optional, no useful default\n\nCalled after the image has been loaded (and the aspect ratio has been calculated).\n\n#### onError\n\n\u003e `function(error: string)` | optional, no useful default\n\nCalled if the image could not be loaded. Called with the error message in the form of a string.\n\n- `error`: the error message as a string\n\n#### source\n\n\u003e `number`/`object` | _required_\n\nThe source for your `Image`. This can be a local file resource (the result of an `import` or\n`require` statement) or an object containing a `uri` key with a remote URL as its value.\n\n### Advanced Inputs\n\n#### aspectRatio\n\n\u003e `number` | **control prop**, default: automatically calculated from image dimensions\n\nBy default, `react-native-responsive-image-view` manages this value internally based on the\ndimensions of the source image. However, if more control is needed, you can pass in a fixed aspect\nratio to use instead. This is useful if you want to fit the image into a statically shaped box such\nas a navigation drawer header.\n\n### Component-only Inputs\n\n#### Render Prop Function\n\nThis is where you render whatever you want to based on the state of\n`react-native-responsive-image-view` when using the component (not applicable when using the hook).\nIt's just a function or component, available in a few different ways. Read Donavon West's very\nopinionated but informative [post about them][faccs-and-ci] for more information. They all receive\nthe same props, so it is purely a stylistic choice left up to you as the consumer.\n\n```tsx\n// component injection\n\u003cResponsiveImageView component={/* right here */} /\u003e\n\n// render prop\n\u003cResponsiveImageView render={/* right here */} /\u003e\n\n// function-as-children\n\u003cResponsiveImageView\u003e\n  {/* right here */}\n\u003c/ResponsiveImageView\u003e\n```\n\nChoose your approach by passing one of the following props:\n\n##### component\n\n\u003e `component` | _optional_\n\nThis is rendered with an object passed in as `props`. Read more about the properties of this object\nin the [Output](#output) section.\n\n##### render\n\n\u003e `function({})` | _optional_\n\nThis is called with an object. Read more about the properties of this object in the\n[Output](#output) section.\n\n##### children\n\n\u003e `function({})` | _optional_\n\nThis is called with an object. Read more about the properties of this object in the\n[Output](#output) section.\n\n**N.B.** Multiple render methods should not be combined, but in the event that they are,\n`react-native-responsive-image-view` will honor the following order:\n\n1.  `component`\n1.  `render`\n1.  function as `children`\n1.  non-functional `children` (render children normally)\n1.  `null` (render nothing)\n\n## Output\n\nRegardless of whether you are using the component or the hook, the results are an object containing\nimportant properties you'll need for rendering. It will be passed to the\n[Render Prop Function](#render-prop-function) when using the component, and returned from the hook\ninvocation when using the hook. The properties of this object can be split into the following\ncategories:\n\n### prop getters\n\n\u003e See [this blog post about prop getters][kent-prop-getters]\n\nThese functions are used to apply props to the elements that you render. This gives you maximum\nflexibility to render what, when, and wherever you like. You call these on the element in question\n(for example: `\u003cView {...getViewProps()}`)). It's advisable to pass all your props to that function\nrather than applying them on the element yourself to avoid your props being overridden (or\noverriding the props returned). For example: `getViewProps({ hitSlop: myHitSlop })`.\n\n| property        | type           | description                                                                     |\n| --------------- | -------------- | ------------------------------------------------------------------------------- |\n| `getViewProps`  | `function({})` | returns the props you should apply to the `View` (parent of `Image`) you render |\n| `getImageProps` | `function({})` | returns the props you should apply to the `Image` (child of `View`) you render  |\n\n#### `getViewProps`\n\nThis method should be applied to the `View` you render. It is recommended that you pass all props as\nan object to this method which will compose together any of the props you need to apply to the\n`View` while preserving the ones that `react-native-responsive-image-view` needs to apply to make\nthe `View` behave.\n\nThere are no required properties for this method.\n\n#### `getImageProps`\n\nThis method should be applied to the `Image` you render. It is recommended that you pass all props\nas an object to this method which will compose together any of the props you need to apply to the\n`Image` while preserving the ones that `react-native-responsive-image-view` needs to apply to make\nthe `Image` behave.\n\nThere are no required properties for this method.\n\n### state\n\nThese are values that represent the current state of the component.\n\n| property  | type      | description                                                    |\n| --------- | --------- | -------------------------------------------------------------- |\n| `loading` | `boolean` | whether or not the image is currently loading                  |\n| `error`   | `string`  | an error message if the image failed to load (`''` on success) |\n\n### utils\n\nThese are miscellaneous helpers that don't fit in the other major categories.\n\n| property | type         | description                                           |\n| -------- | ------------ | ----------------------------------------------------- |\n| `retry`  | `function()` | force another attempt to resolve the image dimensions |\n\n## Examples\n\nSee the [`examples`][examples-directory] directory for examples using both the component and the\nhook.\n\n## Snack Playground\n\nCheck out the [Snack Playground][snack-playground] for an interactive experience where you can try\nout the various usage patterns. You can see the code run live on your own device via [Expo\nGo][expo-go], or enable the Preview option to use the in-browser simulators!\n\n\u003e Note: Snack's underlying build system, `snackager`,\n\u003e [cannot currently handle](https://github.com/expo/snack/issues/383) some TypeScript features used\n\u003e in this library, so the version showcased in the playground is pinned to the latest pre-TypeScript\n\u003e implementation. We hope the Expo team can resolve this soon, but it should still provide a useful\n\u003e environment to try out the library in the meantime.\n\n## Inspiration\n\nI was heavily inspired by [`react-native-flex-image`][react-native-flex-image] from\n[KodeFox][kodefox] (see the [Other Solutions](#other-solutions) section) with regards to how to\ndisplay the image to get the desired behavior. The original implementation and API were primarily\ninspired by [Michael Jackson][mjackson]'s [\"Use a Render Prop!\"][use-a-render-prop] post and video,\nas well as [Kent C. Dodds][kentcdodds]' [introduction to prop getters][kent-prop-getters].\n\n## Other Solutions\n\nAfter scouring [npm][npm] for solutions and trying most (if not all) of them, the best option I\nfound was the following:\n\n- [`react-native-flex-image`][react-native-flex-image]\n\nUnfortunately, it is too restrictive for my use cases. It renders the magic `\u003cView\u003e\u003cImage /\u003e\u003c/View\u003e`\ncombination for you, preventing you from customizing the layout. For example, it provides an\n`onPress` prop if you want to make the `Image` touchable, but it wraps the `Image` in a\n`TouchableOpacity` (what if I wanted a `TouchableHighlight` instead?). It also renders its own\nloading indicator (an `ActivityIndicator`) as well as error messages (as `Text`). At the end of the\nday, these features proved to be too opinionated.\n\n## LICENSE\n\n[MIT][license]\n\n[npm-image]: https://img.shields.io/npm/v/react-native-responsive-image-view.svg?style=flat-square\n[npm-url]: https://www.npmjs.com/package/react-native-responsive-image-view\n[ci-image]:\n  https://img.shields.io/github/actions/workflow/status/wKovacs64/react-native-responsive-image-view/ci.yml?logo=github\u0026style=flat-square\n[ci-url]:\n  https://github.com/wKovacs64/react-native-responsive-image-view/actions?query=workflow%3Aci\n[coverage-image]:\n  https://img.shields.io/codecov/c/github/wKovacs64/react-native-responsive-image-view/main.svg?style=flat-square\n[coverage-url]: https://codecov.io/gh/wKovacs64/react-native-responsive-image-view/branch/main\n[aspectratio]: https://facebook.github.io/react-native/docs/layout-props#aspectratio\n[render-props]:\n  https://react.dev/reference/react/Children#calling-a-render-prop-to-customize-rendering\n[custom-hooks]: https://react.dev/learn/reusing-logic-with-custom-hooks\n[npm]: https://www.npmjs.com/\n[react-native-flex-image]: https://github.com/kodefox/react-native-flex-image\n[snack-playground]: https://snack.expo.dev/@wkovacs64/responsiveimageview\n[expo-go]: https://expo.dev/client\n[kodefox]: https://github.com/kodefox\n[mjackson]: https://github.com/mjackson\n[use-a-render-prop]: https://medium.com/@mjackson/use-a-render-prop-50de598f11ce\n[faccs-and-ci]: http://americanexpress.io/faccs-are-an-antipattern/\n[kentcdodds]: https://github.com/kentcdodds\n[kent-prop-getters]:\n  https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters\n[examples-directory]:\n  https://github.com/wKovacs64/react-native-responsive-image-view/tree/main/examples\n[license]: https://github.com/wKovacs64/react-native-responsive-image-view/tree/main/LICENSE.txt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwkovacs64%2Freact-native-responsive-image-view","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwkovacs64%2Freact-native-responsive-image-view","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwkovacs64%2Freact-native-responsive-image-view/lists"}