DEV Community

George K.
George K.

Posted on

How to make a dynamic background for React Native apps loading from API

Image description

There are tons of cool APIs where we can get images from for our apps. In this guide we are going to use Pixabay API for loading background images. You will need to get an API key from pixabay.com.

Import ImageBackground element from react-native

import { ImageBackground} from 'react-native';
Enter fullscreen mode Exit fullscreen mode

Add ImageBackground as the parent element in your component where you want to apply it and add styles:

export default function SomeComponent(props) {
  return (
    // rendering ImageBackground element with backgroundImage from state passed as source of the image
    <ImageBackground
    source={{ uri: backgroundImage }}
    style={styles.background}
    >
    <View style={styles.app}>
  </View>
  </ImageBackground>
  );
}
Enter fullscreen mode Exit fullscreen mode

Styles:

const styles = StyleSheet.create({
  background: {
    flex: 1,
    resizeMode: "cover",
    justifyContent: "flex-end"
  },
  app: {
    marginHorizontal: "auto",
    maxWidth: 500,
    backGroundColor: "transparent"
  }
});
Enter fullscreen mode Exit fullscreen mode

Import useState and declare state variable for the image with some default image:

import {useState} from 'react'
Enter fullscreen mode Exit fullscreen mode
  // declare state variable for single background image, initially some image
  const [backgroundImage, setBackgroundImage] = useState("https://pixabay.com/get/g5087a1cec28279208368920fd3d30343bf08ca1002b5316e4cdd8fac66e19af31811080dc13c67f0f49c113298c4724166f201a96b48651d0b49efddfea5d2b6_640.jpg");
Enter fullscreen mode Exit fullscreen mode

Add a function to fetch the images from some API, for example from Pixabay:

// Please add your api key which you can get from pixabay.com  
  const pixabayAPIkey='YOUR API KEY'
  let newBackground = () => {
    // sending request to the API
    fetch(
      `https://pixabay.com/api/?key=${pixabayAPIkey}&q=cat&orientation=vertical&safesearch=true&per_page=100`
      )
    .then((data) => {
      return data.json();
    })
    .then((pics) => {
        // creating a random number for index to pick one of the images from 100 we will get
        let randomImage = parseInt(Math.random() * pics.totalHits);
        // set this random image to tbe the current background
        setBackgroundImage(pics.hits[randomImage].largeImageURL);
        // set all images in state to use later for changing the background
        setAllImages(pics.hits);
      })
    .catch((err) => {
      console.log(err);
    })
    .finally(() => console.log("Finally: ", backgroundImage, allImages.length));
  };
  // executing the function only on first load once, no need for useEffect
  newBackground();
Enter fullscreen mode Exit fullscreen mode

In this function we will get an array of images, so let's save them in state and then use to update backgrounds instead of sending a new request every time during the lifecycle of component and abuse API.

We will add a state variable to keep all those images:

  // declare state variable for all images we will get from API
  const [allImages, setAllImages] = useState([]);
Enter fullscreen mode Exit fullscreen mode

it will be updated from the newBackground with setAllImages(pics.hits)

Now on first render we will get a bunch of images and set one of them to be the current background.

We can also add a button to change the background manually just to check. You can replace the button by some event created by user or your app to do it.

<Button title="New Kitty" onPress={()=>allImages.length>0&&updateBackground()} />
Enter fullscreen mode Exit fullscreen mode

So the final code looks like that:

import React from "react";
// import all the elements we will use from react-native
import { ImageBackground, Button, StyleSheet, View } from "react-native";
// import useState
import { useState } from "react";

function App() {
  // declare state variable for single background image, initially some image
  const [backgroundImage, setBackgroundImage] = useState("https://pixabay.com/get/g5087a1cec28279208368920fd3d30343bf08ca1002b5316e4cdd8fac66e19af31811080dc13c67f0f49c113298c4724166f201a96b48651d0b49efddfea5d2b6_640.jpg");
  // declare state variable for all images we will get from API
  const [allImages, setAllImages] = useState([]);
  // Please add your api key which you can get from pixabay.com  
  const pixabayAPIkey='YOUR API KEY'
  let newBackground = () => {
    // sending request to the API
    fetch(
      `https://pixabay.com/api/?key=${pixabayAPIkey}&q=cat&orientation=vertical&safesearch=true&per_page=100`
      )
    .then((data) => {
      return data.json();
    })
    .then((pics) => {
        // creating a random number for index to pick one of the images from 100 we will get
        let randomImage = parseInt(Math.random() * pics.totalHits);
        // set this random image to tbe the current background
        setBackgroundImage(pics.hits[randomImage].largeImageURL);
        // set all images in state to use later for changing the background
        setAllImages(pics.hits);
      })
    .catch((err) => {
      console.log(err);
    })
    .finally(() => console.log("Finally: ", backgroundImage, allImages.length));
  };
  // executing the function only on first load once, no need for useEffect
  newBackground();

  // updating background from state
  const updateBackground = () => {
    // generating random index
    let randomImage = parseInt(Math.random() * (allImages.length - 1));
    // setting random image from images array in state to be the current background
    setBackgroundImage(allImages[randomImage].largeImageURL);
  };

  return (
    // rendering ImageBackground element with backgroundImage from state passed as source of the image
    <ImageBackground
    source={{ uri: backgroundImage }}
    style={styles.background}
    >
    <View style={styles.app}>
  {/* button to trigger change of the background if we have images in the allImages */}
  <Button title="New Kitty" onPress={()=>allImages.length>0&&updateBackground()} />
  </View>
  </ImageBackground>
  );
}

const styles = StyleSheet.create({
  background: {
    flex: 1,
    resizeMode: "cover",
    justifyContent: "flex-end"
  },
  app: {
    marginHorizontal: "auto",
    maxWidth: 500,
    backGroundColor: "transparent"
  }
});

export default App;
Enter fullscreen mode Exit fullscreen mode

Here is the sandbox with code.

That's it :)

Top comments (0)