New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-native-responsive-image-view

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-responsive-image-view

React Native component for scaling an Image within the parent View

1.0.0-alpha.0
Source
npm
Version published
Weekly downloads
640
-10.74%
Maintainers
1
Weekly downloads
 
Created
Source

react-native-responsive-image-view

React Native component for scaling an Image within the parent View

npm Version Build Status Code Coverage

The problem

You want to display an image in your React Native app that fills the width of its container and scales its height according to the aspect ratio of the image. If you're coming from front-end web development, you may be familiar with Bootstrap 3's img-responsive class or manually applying max-width: 100% and height: auto to an image. Unfortunately, auto is not a valid value for height in React Native, so that technique doesn't quite translate.

This solution

This is a component that calculates the aspect ratio of your image for you (or uses a fixed value, if you supply one) and provides you with the appropriate props to apply to a View container and an Image inside it which will produce the results you're looking for. The secret sauce is setting both the height and width attributes of the style prop on the Image to 100% and wrapping it with a View that has its aspectRatio prop set to match the aspect ratio you want. It uses a render prop which gives you maximum flexibility with a minimal API because you are responsible for the rendering of everything and you simply apply props to what you're rendering.

Table of Contents

Installation

Using yarn:

yarn add react-native-responsive-image-view

Or, npm:

npm install --save react-native-responsive-image-view

This package also depends on react, prop-types, and react-native. Please make sure you have those installed as well.

Usage

import React from 'react';
import { Image, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

export default ({ imageUri }) => (
  <ResponsiveImageView
    source={{ uri: imageUri }}
    render={({ getViewProps, getImageProps }) => (
      <View {...getViewProps()}>
        <Image {...getImageProps()} />
      </View>
    )}
  />
);

N.B. This component doesn't render anything itself, it just calls your render function and renders that. "Use a render prop!" Just be sure to render the Image inside the View in your render function.

Props

aspectRatio

number | optional, default: automatically calculated from image dimensions

A fixed aspect ratio to use instead of calculating one from the image. This is useful if you want to fit the image into a statically shaped box such as a navigation drawer header.

onLoad

function() | optional, no useful default

Called after the image has been loaded (and the aspect ratio has been calculated).

onError

function(error: string) | optional, no useful default

Called if the image could not be loaded. Called with the error message in the form of a string.

  • error: the error message as a string

source

number/object | required

The source for your Image. This can be a local file resource (the result of an import or require statement) or an object containing a uri key with a remote URL as its value.

render

function({}) | required

This is called with an object. Read more about the properties of this object in the Render Prop Function section.

Render Prop Function

This is where you render whatever you want to based on the state of react-native-responsive-image-view. It's a regular prop called render:

<ResponsiveImageView render={/* right here */} />

The function you pass in as the render prop gets called with an object containing important properties you'll need for rendering. The properties of this object can be split into two categories as indicated below:

prop getters

See this blog post about prop getters

These functions are used to apply props to the elements that you render. This gives you maximum flexibility to render what, when, and wherever you like. You call these on the element in question (for example: <View {...getViewProps()})). It's advisable to pass all your props to that function rather than applying them on the element yourself to avoid your props being overridden (or overriding the props returned). For example: getViewProps({ hitSlop: myHitSlop }).

propertytypedescription
getViewPropsfunction({})returns the props you should apply to the View (parent of Image) you render
getImagePropsfunction({})returns the props you should apply to the Image (child of View) you render
getViewProps

This method should be applied to the View you render. It is recommended that you pass all props as an object to this method which will compose together any of the props you need to apply to the View while preserving the ones that react-native-responsive-image-view needs to apply to make the View behave.

There are no required properties for this method.

getImageProps

This method should be applied to the Image you render. It is recommended that you pass all props as an object to this method which will compose together any of the props you need to apply to the Image while preserving the ones that react-native-responsive-image-view needs to apply to make the Image behave.

There are no required properties for this method.

state

These are values that represent the current state of the component.

propertytypedescription
loadingbooleanwhether or not the image is currently loading
errorstringan error message if the image failed to load ('' on success)

Examples

Responsive Remote Image
import React from 'react';
import { Image, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

const MyComponent = ({ imageUri }) => (
  <ResponsiveImageView
    source={{ uri: imageUri }}
    render={({ getViewProps, getImageProps }) => (
      <View {...getViewProps()}>
        <Image {...getImageProps()} />
      </View>
    )}
  />
);
Fixed Aspect Ratio and Local Image Resource
import React from 'react';
import { Image, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';
import headerImage from './header.jpg';

const DrawerHeader = () => (
  <ResponsiveImageView
    aspectRatio={16 / 9}
    source={headerImage}
    render={({ getViewProps, getImageProps }) => (
      <View {...getViewProps()}>
        <Image {...getImageProps()} />
      </View>
    )}
  />
);
Touchable
import React from 'react';
import { Image, TouchableHighlight, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

const MyTouchableComponent = ({ imageUri, onPress }) => (
  <ResponsiveImageView
    source={{ uri: imageUri }}
    render={({ getViewProps, getImageProps }) => (
      <View {...getViewProps()}>
        <TouchableHighlight onPress={onPress}>
          <Image {...getImageProps()} />
        </TouchableHighlight>
      </View>
    )}
  />
);
Loading and Error Handling
import React from 'react';
import { ActivityIndicator, Image, Text, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

const MyComponent = ({ imageUri }) => (
  <ResponsiveImageView
    source={{ uri: imageUri }}
    render={({ error, loading, getViewProps, getImageProps }) => {
      if (loading) {
        return <ActivityIndicator animating={true} size="large" />;
      }
      if (error) {
        return (
          <View>
            <Text>{error}</Text>
          </View>
        );
      }
      return (
        <View {...getViewProps()}>
          <Image {...getImageProps()} />
        </View>
      );
    }}
  />
);
Composing Props
import React from 'react';
import { StyleSheet, Image, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

const styles = StyleSheet.create({
  imageContainer: {
    padding: 20, // will be merged into ResponsiveImageView View props!
  },
  image: {
    width: '50%', // will be overwritten by ResponsiveImageView Image props!
  },
});

const MyComponent = ({ imageUri }) => (
  <ResponsiveImageView
    source={{ uri: imageUri }}
    render={({ getViewProps, getImageProps }) => (
      <View {...getViewProps({ style: styles.imageContainer })}>
        <Image {...getImageProps({ style: styles.image })} />
      </View>
    )}
  />
);
Success/Failure Callbacks
import { Component } from 'react';
import { Image, View } from 'react-native';
import ResponsiveImageView from 'react-native-responsive-image-view';

class MyStatefulComponent extends Component {
  state = {
    success: false,
    error: '',
  };

  onLoad = () => {
    this.setState({
      success: true,
      error: '',
    });
  };

  onError = error => {
    this.setState({
      success: false,
      error,
    });
  };

  renderImageView = ({ getViewProps, getImageProps }) => (
    <View {...getViewProps()}>
      <Image {...getImageProps()} />
    </View>
  );

  render() {
    return (
      <ResponsiveImageView
        onLoad={this.onLoad}
        onError={this.onError}
        source={{ uri: this.props.imageUri }}
        render={this.renderImageView}
      />
    );
  }
}

Inspiration

I was heavily inspired by react-native-flex-image from KodeFox (see the Other Solutions section) with regards to how to display the image to get the desired behavior. For the actual implementation and API, I was primarily inspired by Michael Jackson's "Use a Render Prop!" post and video, as well as Kent C. Dodds' introduction to prop getters (popularized by his downshift project, which also provided inspiration for this README).

Other Solutions

After scouring npm for solutions and trying most (if not all) of them, the best option I found was the following:

Unfortunately, it is too restrictive for my use cases. It renders the magic <View><Image /></View> combination for you, preventing you from customizing the layout. For example, it provides an onPress prop if you want to make the Image touchable, but it wraps the Image in a TouchableOpacity (what if I wanted a TouchableHighlight instead?). It also renders its own loading indicator (an ActivityIndicator) as well as error messages (as Text). At the end of the day, these features proved to be too opinionated.

LICENSE

MIT

Keywords

react

FAQs

Package last updated on 13 Dec 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts