# Channel Background Customization

## Basic Custom Background

You can change the background statically by wrapping `MessageList` and `MessageInput` with the `ImageBackground` component.

![167857632 C0bc9d67 0a84 4cf5 9d75 305e3bcd1f3d](https://user-images.githubusercontent.com/25864161/167857632-c0bc9d67-0a84-4cf5-9d75-305e3bcd1f3d.png)

Also make sure you adjust the `theme` correctly.

```tsx
import {
  Channel,
  MessageInput,
  MessageList,
  ThemeProvider,
} from "stream-chat-react-native";
import { ImageBackground } from "react-native";

export const theme = {
  messageList: {
    container: {
      backgroundColor: "transparent",
    },
  },
};

const IMAGE_URI =
  "https://images.unsplash.com/photo-1549125764-91425ca48850?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8NjF8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60";

const ChannelScreen = ({ channel }) => (
  <ThemeProvider style={theme}>
    <Channel channel={channel}>
      <ImageBackground
        style={{ flex: 1 }}
        source={{
          uri: IMAGE_URI,
        }}
      >
        <MessageList />
        <MessageInput />
      </ImageBackground>
    </Channel>
  </ThemeProvider>
);
```

---

## Custom Background With Selection Screen

In this step, we will add a button that will navigate to a separate screen, where the user will be able to select their
favorite background image for a specific channel.

<table>
  <tr>
  <td align='center' width='50%'>

![168006715 Acae4b85 00cb 4b45 A127 Aa8f94c13895](https://user-images.githubusercontent.com/25864161/168006715-acae4b85-00cb-4b45-a127-aa8f94c13895.png)

  </td>
  <td align='center' width='50%'>

![168006193 8fd4ad85 7553 4956 A7c6 5d6979e15ee4](https://user-images.githubusercontent.com/25864161/168006193-8fd4ad85-7553-4956-a7c6-5d6979e15ee4.png)

  </td>
  </tr>
  <tr></tr>
  <tr>
  <td align='center'>
      <strong>Chat screen with customize background button</strong>
  </td>
  <td align='center'>
      <strong>Wallpaper overview screen with background image options</strong>
  </td>
  </tr>
</table>

### Store and manage channel preferences

To persist the channel preferences (at the moment, only the URI of the selected background), we will need to store some data.
We will do it by using `react-native-mmkv`, a key-value storage [framework](https://github.com/mrousavy/react-native-mmkv#mmkv).

Follow the [installation steps](https://github.com/mrousavy/react-native-mmkv#installation), and let's get started, shall we?

We will start by creating our `ChannelBackgroundView` component.
This component will be in charge of rendering the custom background by retrieving it from our key-value store.
We save an object to a key-value store to be scalable and future-proof.
You might want to add other preferences later, such as dimming value, background color, etc.

```tsx
import type { ViewProps } from "react-native";
import { useMMKVObject } from "react-native-mmkv";

type ChannelPreferences = {
  imageUri: string;
};

const DEFAULT_BACKGROUND_URI = "https://i.redd.it/3jfjc53fsyb61.jpg";

const ChannelBackgroundView = ({
  channelId,
  ...props
}: {
  channelId: string;
} & ViewProps) => {
  const [channelPreferences] = useMMKVObject<ChannelPreferences>(channelId);
  const uri = channelPreferences?.imageUri || DEFAULT_BACKGROUND_URI;

  return <ImageBackground {...props} source={{ uri }} />;
};
```

We will then use it in our previously built `ChannelScreen`.
Replace the static `ImageBackground` with `ChannelBackgroundView` and pass the `channelId`.

```tsx
const ChannelScreen = ({ channel }) => {
  return (
    <ThemeProvider style={theme}>
      <Channel channel={channel}>
        <ChannelBackgroundView channelId={channel?.id} style={{ flex: 1 }}>
          <MessageList />
          <MessageInput />
        </ChannelBackgroundView>
      </Channel>
    </ThemeProvider>
  );
};
```

---

### Wallpaper overview screen

Let's now add a screen where the user can choose a wallpaper from a particular predefined list of images.

```tsx
import { StackNavigationProp } from "@react-navigation/stack";
import { RouteProp } from "@react-navigation/native";
import { useMMKVObject } from "react-native-mmkv";
import { View, SafeAreaView, Pressable, Image, StyleSheet } from "react-native";

const WallpaperOverviewScreen = ({
  navigation: { navigate },
  route: {
    params: { channelId },
  },
}: WallpaperOverviewScreenProps) => {
  const [_, setChannelPreferences] =
    useMMKVObject<ChannelPreferences>(channelId);
  return (
    <SafeAreaView
      style={{
        flex: 1,
        justifyContent: "center",
      }}
    >
      <View style={styles.container}>
        {BRIGHT_IMAGES?.map(({ imageUri = "" }, i) => {
          const handleOnPress = () => {
            setChannelPreferences({ imageUri });
            navigate("Channel");
          };
          return (
            <Pressable
              key={i}
              onPress={handleOnPress}
              style={{
                margin: 1,
                width: GRID_ITEM_WIDTH,
              }}
            >
              <Image style={styles.image} source={{ uri: imageUri }} />
            </Pressable>
          );
        })}
      </View>
    </SafeAreaView>
  );
};

type StackNavigatorParamList = {
  WallpaperOverviewScreen: {
    channelId: string;
  };
};

type WallpaperOverviewScreenProps = {
  navigation: StackNavigationProp<
    StackNavigatorParamList,
    "WallpaperOverviewScreen"
  >;
  route: RouteProp<StackNavigatorParamList, "WallpaperOverviewScreen">;
};

type ChannelPreferences = {
  imageUri: string;
};

const GRID_ITEM_WIDTH = "32.7%";

// Some random images that will get you started
const BRIGHT_IMAGES = [
  "https://images.unsplash.com/photo-1549125764-91425ca48850?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8NjF8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1549241520-425e3dfc01cb?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8ODB8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1554226321-24fdcddd5a55?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MjE5fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1550006490-9f0656b79e9d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8ODl8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1551506448-074afa034c05?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTEzfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553114835-6f7674d3c2c0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTMyfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553075712-453f7213c24f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTMzfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1551917951-148edcd8ea8d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTU3fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553969923-bbf0cac2666b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MjA3fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553194642-29b272a173b9?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTcwfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553356084-58ef4a67b2a7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTcxfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
  "https://images.unsplash.com/photo-1553526777-5ffa3b3248d8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxleHBsb3JlLWZlZWR8MTk4fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=800&q=60",
].map((imageUri) => ({
  imageUri,
}));

const styles = StyleSheet.create({
  container: {
    flexDirection: "row",
    flex: 1,
    alignContent: "stretch",
    flexWrap: "wrap",
    padding: 6,
  },
  image: {
    flex: 1,
    width: "100%",
  },
});
```

<admonition type="note">

Be aware of the fact that channel preferences were implemented with MMKV, a key-value storage framework.
There are alternative approaches to achieving the same goal, such as saving the channel preferences as [custom data](/chat/docs/javascript/channel-update/) on Stream's channel object.

</admonition>

### Add a configuration button

We will now add a button that will take the user from the Channel screen to our new WallpaperOverview screen.

```tsx
import { useNavigation } from "@react-navigation/native";
import {
  Channel,
  MessageInput,
  MessageList,
  ThemeProvider,
} from "stream-chat-react-native";
import { Pressable, Text, StyleSheet } from "react-native";

const ChannelScreen = ({ channel }) => {
  const { navigate } = useNavigation();
  const handleMenuOnPress = () =>
    navigate("WallpaperOverviewScreen", { channelId: channel?.id });

  return (
    <ThemeProvider style={theme}>
      <Channel channel={channel}>
        <ChannelBackgroundView channelId={channel?.id} style={{ flex: 1 }}>
          <Pressable style={styles.menuButton} onPress={handleMenuOnPress}>
            <Text>🎨</Text>
          </Pressable>
          <MessageList />
          <MessageInput />
        </ChannelBackgroundView>
      </Channel>
    </ThemeProvider>
  );
};

const styles = StyleSheet.create({
  menuButton: {
    position: "absolute",
    right: 0,
    top: 0,
    backgroundColor: "rgba(255,87,56,0.65)",
    borderRadius: 36,
    padding: 16,
    margin: 16,
    alignItems: "center",
    zIndex: 10,
  },
});

export const theme = {
  messageList: {
    container: {
      backgroundColor: "transparent",
    },
  },
};
```

---

### Optional: Connect all screens by navigation

If applicable to your use case, add our screens to a Navigation Stack by doing the following:

```tsx
import { createNativeStackNavigator } from "react-native-screens/native-stack";
import { NavigationContainer } from "@react-navigation/native";

const Stack = createNativeStackNavigator();

export default () => {
  return (
    <SafeAreaProvider>
      <ThemeProvider style={theme}>
        <NavigationContainer>
          <Stack.Navigator initialRouteName="Channel">
            <Stack.Screen
              component={ChannelScreen}
              name="Channel"
              options={noHeaderOptions}
            />
            <Stack.Screen
              component={WallpaperOverviewScreen}
              name="WallpaperOverviewScreen"
            />
          </Stack.Navigator>
        </NavigationContainer>
      </ThemeProvider>
    </SafeAreaProvider>
  );
};
```


---

This page was last updated at 2026-07-21T09:57:59.553Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v4/guides/channel-background-customization/](https://getstream.io/chat/docs/sdk/react-native/v4/guides/channel-background-customization/).