Bird
Raised Fist0
React Nativemobile~20 mins

Modal and bottom sheet in React Native - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Modal and Bottom Sheet Demo
This screen shows how to open a modal and a bottom sheet. The modal appears in the center with a message and a close button. The bottom sheet slides up from the bottom with some options and a close button.
Target UI
-------------------------
| Modal and Bottom Sheet |
|-----------------------|
| [Open Modal]          |
| [Open Bottom Sheet]   |
|                       |
|                       |
-------------------------
Add a button labeled 'Open Modal' that opens a modal in the center of the screen.
The modal should have a message 'This is a modal' and a button 'Close' to close it.
Add a button labeled 'Open Bottom Sheet' that opens a bottom sheet sliding up from the bottom.
The bottom sheet should have a message 'This is a bottom sheet' and a button 'Close' to close it.
Use React Native's Modal component for the modal.
Use a View with animation or React Native's built-in components to simulate the bottom sheet.
Ensure both modal and bottom sheet can be closed by their respective close buttons.
Starter Code
React Native
import React, { useState } from 'react';
import { View, Text, Button, Modal, StyleSheet, Animated, TouchableOpacity } from 'react-native';

export default function ModalBottomSheetDemo() {
  const [modalVisible, setModalVisible] = useState(false);
  const [bottomSheetVisible, setBottomSheetVisible] = useState(false);

  // TODO: Add animation state and handlers for bottom sheet

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setModalVisible(true)} />
      <Button title="Open Bottom Sheet" onPress={() => setBottomSheetVisible(true)} />

      <Modal
        visible={modalVisible}
        transparent={true}
        animationType="fade"
        onRequestClose={() => setModalVisible(false)}
      >
        {/* TODO: Add modal content here */}
      </Modal>

      {/* TODO: Add bottom sheet view here */}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
  },
  // TODO: Add styles for modal and bottom sheet
});
Task 1
Task 2
Task 3
Task 4
Solution
React Native
import React, { useState, useRef, useEffect } from 'react';
import { View, Text, Button, Modal, StyleSheet, Animated, TouchableOpacity, Dimensions } from 'react-native';

const screenHeight = Dimensions.get('window').height;

export default function ModalBottomSheetDemo() {
  const [modalVisible, setModalVisible] = useState(false);
  const [bottomSheetVisible, setBottomSheetVisible] = useState(false);
  const slideAnim = useRef(new Animated.Value(screenHeight)).current;

  useEffect(() => {
    if (bottomSheetVisible) {
      Animated.timing(slideAnim, {
        toValue: screenHeight - 250,
        duration: 300,
        useNativeDriver: false
      }).start();
    } else {
      Animated.timing(slideAnim, {
        toValue: screenHeight,
        duration: 300,
        useNativeDriver: false
      }).start();
    }
  }, [bottomSheetVisible, slideAnim]);

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setModalVisible(true)} />
      <View style={{ height: 20 }} />
      <Button title="Open Bottom Sheet" onPress={() => setBottomSheetVisible(true)} />

      <Modal
        visible={modalVisible}
        transparent={true}
        animationType="fade"
        onRequestClose={() => setModalVisible(false)}
      >
        <View style={styles.modalBackground}>
          <View style={styles.modalBox}>
            <Text style={styles.modalText}>This is a modal</Text>
            <Button title="Close" onPress={() => setModalVisible(false)} />
          </View>
        </View>
      </Modal>

      <Animated.View style={[styles.bottomSheet, { top: slideAnim }]}>
        <Text style={styles.sheetText}>This is a bottom sheet</Text>
        <TouchableOpacity style={styles.closeButton} onPress={() => setBottomSheetVisible(false)}>
          <Text style={styles.closeButtonText}>Close</Text>
        </TouchableOpacity>
      </Animated.View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingHorizontal: 20,
    backgroundColor: '#fff'
  },
  modalBackground: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.5)',
    justifyContent: 'center',
    alignItems: 'center'
  },
  modalBox: {
    width: 300,
    padding: 20,
    backgroundColor: 'white',
    borderRadius: 10,
    alignItems: 'center'
  },
  modalText: {
    fontSize: 18,
    marginBottom: 15
  },
  bottomSheet: {
    position: 'absolute',
    left: 0,
    width: '100%',
    height: 250,
    backgroundColor: 'white',
    borderTopLeftRadius: 15,
    borderTopRightRadius: 15,
    padding: 20,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: -3 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 5
  },
  sheetText: {
    fontSize: 18,
    marginBottom: 20
  },
  closeButton: {
    backgroundColor: '#2196F3',
    paddingVertical: 10,
    borderRadius: 5,
    alignItems: 'center'
  },
  closeButtonText: {
    color: 'white',
    fontSize: 16
  }
});

We use React Native's Modal component to show a modal in the center with a semi-transparent dark background. The modal box contains a message and a close button that sets modalVisible to false.

For the bottom sheet, we use an Animated.View that slides up from the bottom. We animate its top position from off-screen (screen height) to visible (screen height - 250). The bottom sheet has a message and a close button that hides it by setting bottomSheetVisible to false.

This approach keeps UI simple and uses React Native's built-in components and animation for smooth transitions.

Final Result
Completed Screen
-------------------------
| Modal and Bottom Sheet |
|-----------------------|
| [Open Modal]          |
|                       |
| [Open Bottom Sheet]   |
|                       |
|                       |
-------------------------

When 'Open Modal' is tapped:
  -------------------------
  |                       |
  |   This is a modal     |
  |   [Close]             |
  |                       |
  -------------------------

When 'Open Bottom Sheet' is tapped:
  -------------------------
  |                       |
  |                       |
  |                       |
  |-----------------------|
  | This is a bottom sheet|
  | [Close]               |
  -------------------------
Tapping 'Open Modal' shows a centered modal with a message and a close button.
Tapping 'Close' inside modal hides the modal.
Tapping 'Open Bottom Sheet' slides up a bottom sheet from the bottom with a message and close button.
Tapping 'Close' inside bottom sheet slides it down and hides it.
Stretch Goal
Add swipe down gesture to close the bottom sheet.
💡 Hint
Use PanResponder or Gesture Handler to detect swipe down and set bottomSheetVisible to false.

Practice

(1/5)
1. What is the main purpose of a Modal component in React Native?
easy
A. To display content over the current screen and keep user focus
B. To navigate between different screens
C. To create a permanent footer on the screen
D. To handle background tasks silently

Solution

  1. Step 1: Understand what a Modal does

    A Modal appears on top of the current screen and blocks interaction with the background.
  2. Step 2: Compare options

    Only To display content over the current screen and keep user focus describes this behavior correctly; others describe unrelated features.
  3. Final Answer:

    To display content over the current screen and keep user focus -> Option A
  4. Quick Check:

    Modal = Overlay content [OK]
Hint: Modals block background, focus user attention [OK]
Common Mistakes:
  • Confusing Modal with navigation
  • Thinking Modal is a footer or background task
  • Assuming Modal is always full screen
2. Which of the following is the correct way to control the visibility of a Modal in React Native?
easy
A. <Modal show={true}>
B. <Modal visible={true}>
C. <Modal isVisible={true}>
D. <Modal display={true}>

Solution

  1. Step 1: Recall the correct prop for Modal visibility

    The React Native Modal uses the visible prop to show or hide the modal.
  2. Step 2: Check each option

    Only <Modal visible={true}> uses visible correctly; others use incorrect prop names.
  3. Final Answer:

    <Modal visible={true}> -> Option B
  4. Quick Check:

    Modal visibility prop = visible [OK]
Hint: Use visible prop to toggle Modal display [OK]
Common Mistakes:
  • Using show or isVisible instead of visible
  • Confusing display with visible
  • Forgetting to pass boolean value
3. What will happen when the following React Native code runs?
const [modalVisible, setModalVisible] = React.useState(false);

return (
  <>
    <Button title="Show Modal" onPress={() => setModalVisible(true)} />
    <Modal visible={modalVisible} animationType="slide">
      <View>
        <Text>Hello Modal</Text>
        <Button title="Close" onPress={() => setModalVisible(false)} />
      </View>
    </Modal>
  </>
);
medium
A. The modal appears sliding up when 'Show Modal' is pressed and closes when 'Close' is pressed
B. The modal appears instantly without animation
C. The modal never appears because visible is false initially
D. The modal is always visible and cannot be closed

Solution

  1. Step 1: Understand state controlling Modal visibility

    The state variable modalVisible starts false, so modal is hidden initially.
  2. Step 2: Analyze button actions

    Pressing 'Show Modal' sets modalVisible to true, showing modal with slide animation. 'Close' button sets it back to false, hiding modal.
  3. Final Answer:

    The modal appears sliding up when 'Show Modal' is pressed and closes when 'Close' is pressed -> Option A
  4. Quick Check:

    State controls visible with animation [OK]
Hint: State true shows modal; false hides it [OK]
Common Mistakes:
  • Assuming modal shows without pressing button
  • Ignoring animationType effect
  • Thinking modal cannot be closed
4. Identify the error in this React Native Modal usage:
const [show, setShow] = React.useState(false);

return (
  <Modal visible={show} animationType="fade" onRequestClose={() => setShow(false)}>
    <View>
      <Text>Modal Content</Text>
    </View>
  </Modal>
  <Button title="Open" onPress={() => setShow(true)} />
);
medium
A. The onRequestClose prop is missing
B. The Button component is outside the Modal and will not render
C. Modal must be wrapped inside a single parent element
D. The visible prop should be a string, not boolean

Solution

  1. Step 1: Check JSX structure

    The return statement has two sibling elements: Modal and Button, which is invalid JSX without a wrapper.
  2. Step 2: Identify correct fix

    Wrapping Modal and Button inside a fragment or View fixes the error.
  3. Final Answer:

    Modal must be wrapped inside a single parent element -> Option C
  4. Quick Check:

    JSX requires one parent element [OK]
Hint: Wrap siblings in a fragment or View [OK]
Common Mistakes:
  • Ignoring JSX syntax rules
  • Thinking onRequestClose is optional on Android
  • Confusing visible prop type
5. You want to create a bottom sheet modal that slides up from the bottom and closes when tapping outside it. Which combination of props and components achieves this behavior in React Native?
hard
A. Use Modal visible={false} animationType="slide" transparent={true} with no tap detection
B. Use Modal visible={true} animationType="fade" without transparent prop and no tap detection
C. Use Modal visible={true} animationType="none" transparent={false} with a Button inside
D. Use Modal visible={true} animationType="slide" transparent={true} with a TouchableWithoutFeedback wrapping the background to detect taps

Solution

  1. Step 1: Understand bottom sheet modal requirements

    It must slide up (animationType="slide"), be transparent so background is visible, and detect taps outside to close.
  2. Step 2: Identify correct props and components

    Using transparent={true} allows background taps. Wrapping background in TouchableWithoutFeedback lets you detect taps to close modal.
  3. Step 3: Eliminate wrong options

    Options B, C, and D miss transparency, correct animation, or tap detection.
  4. Final Answer:

    Use <Modal visible={true} animationType="slide" transparent={true}> with a TouchableWithoutFeedback wrapping the background to detect taps -> Option D
  5. Quick Check:

    Slide + transparent + tap detection = bottom sheet [OK]
Hint: Slide + transparent + tap outside closes modal [OK]
Common Mistakes:
  • Forgetting transparent prop for background tap
  • Using fade animation instead of slide
  • Not handling tap outside to close
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard