1

I would like to add an image to my app, which is built using the react-native framework with expo.

I want the Image component to:

  • fill the width of its parent component
  • fit the image's original aspect ratio

I tried setting width: 100%. That does not work in react-native. You have to either set the height to non-auto value or use aspectRatio (or perhaps there is another approach I'm not aware of). When I use aspectRatio, the output looks like this:

import { Image } from "expo-image";
import { memo, useState } from "react";
import { View } from "react-native";
import { Text } from "react-native-paper";

const TheImage = require("@/assets/images/tailwind-logo.svg");

export default memo(function MapLoader() {
  return (
    <View>
      <Image source={TheImage} contentFit="cover" style={{ width: "100%", backgroundColor: "red", aspectRatio: 1 }} />
      <Text variant="displayLarge">React Native</Text>
    </View>
  );
});

enter image description here

As you can see, the Image component (highlighted in red) becomes a square (aspectRatio: 1) and takes up unnecessary space. My alternative approach was to use the onLoad prop to update the correct aspectRatio once the image has loaded. That ultimately works, but causes a brief flash because the component is first rendered with aspectRatio: 1.

import { Image } from "expo-image";
import { memo, useState } from "react";
import { View } from "react-native";
import { Text } from "react-native-paper";

const TheImage = require("@/assets/images/tailwind-logo.svg");

export default memo(function MapLoader() {
  const [aspectRatio, setAspectRatio] = useState<number | undefined>(1);
  return (
    <View>
      <Image
        source={TheImage}
        contentFit="cover"
        style={{ width: "100%", backgroundColor: "red", aspectRatio }}
        onLoad={({ source }) => {
          setAspectRatio(source.width / source.height);
        }}
      />
      <Text variant="displayLarge">React Native</Text>
    </View>
  );
});

enter image description here

My question: how can I render the image so that:

  • it fills the parent container
  • it fits the actual image (image above)
  • it does so without rendering flashes

1 Answer 1

2

The best solution is to get the image size and set the ratio dynamically. Your code can look something like this for full with and dynamic height:

import React from 'react';
import { Image, View } from 'react-native';

export default function FullWidthLocalImage() {
  const source = require('./assets/image.png');
  const { width, height } = Image.resolveAssetSource(source);
  const aspectRatio = width / height;

  return (
    <View style={{ width: '100%' }}>
      <Image
        source={source}
        style={{
          width: '100%',
          aspectRatio,
        }}
        resizeMode="cover"
      />
    </View>
  );
}

For remote images you can use Image.getSize

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.