Bird
Raised Fist0
React Nativemobile~20 mins

File system access in React Native - Mini App: Build & Ship

Choose your learning style10 modes available
Build: File Manager
This screen lets users create, read, and delete a simple text file stored on the device.
Target UI
-------------------------
|      File Manager      |
-------------------------
| Filename: [__________] |
|                       |
| Content:               |
| [                    ] |
| [                    ] |
| [                    ] |
|                       |
| [Save] [Read] [Delete]|
-------------------------
Input field for filename
Multiline input for file content
Save button to write content to file
Read button to load content from file
Delete button to remove the file
Show alert on success or error
Starter Code
React Native
import React, { useState } from 'react';
import { View, TextInput, Button, Alert, StyleSheet, Text } from 'react-native';
import * as FileSystem from 'expo-file-system';

export default function FileManager() {
  const [filename, setFilename] = useState('');
  const [content, setContent] = useState('');

  // TODO: Implement saveFile function

  // TODO: Implement readFile function

  // TODO: Implement deleteFile function

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Filename:</Text>
      <TextInput
        style={styles.input}
        value={filename}
        onChangeText={setFilename}
        placeholder="Enter filename"
        accessibilityLabel="Filename input"
      />
      <Text style={styles.label}>Content:</Text>
      <TextInput
        style={styles.textArea}
        value={content}
        onChangeText={setContent}
        placeholder="Enter file content"
        multiline
        accessibilityLabel="File content input"
      />
      <View style={styles.buttonRow}>
        <Button title="Save" onPress={() => {}} />
        <Button title="Read" onPress={() => {}} />
        <Button title="Delete" onPress={() => {}} />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 20, backgroundColor: '#fff' },
  label: { fontSize: 16, marginBottom: 4 },
  input: { borderWidth: 1, borderColor: '#ccc', padding: 8, marginBottom: 12, borderRadius: 4 },
  textArea: { borderWidth: 1, borderColor: '#ccc', padding: 8, height: 100, textAlignVertical: 'top', borderRadius: 4 },
  buttonRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }
});
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
React Native
import React, { useState } from 'react';
import { View, TextInput, Button, Alert, StyleSheet, Text } from 'react-native';
import * as FileSystem from 'expo-file-system';

export default function FileManager() {
  const [filename, setFilename] = useState('');
  const [content, setContent] = useState('');

  const getFileUri = () => {
    if (!filename) return null;
    return FileSystem.documentDirectory + filename;
  };

  const saveFile = async () => {
    const fileUri = getFileUri();
    if (!fileUri) {
      Alert.alert('Error', 'Please enter a filename');
      return;
    }
    try {
      await FileSystem.writeAsStringAsync(fileUri, content);
      Alert.alert('Success', 'File saved successfully');
    } catch (e) {
      Alert.alert('Error', 'Failed to save file');
    }
  };

  const readFile = async () => {
    const fileUri = getFileUri();
    if (!fileUri) {
      Alert.alert('Error', 'Please enter a filename');
      return;
    }
    try {
      const fileContent = await FileSystem.readAsStringAsync(fileUri);
      setContent(fileContent);
      Alert.alert('Success', 'File read successfully');
    } catch (e) {
      Alert.alert('Error', 'Failed to read file');
    }
  };

  const deleteFile = async () => {
    const fileUri = getFileUri();
    if (!fileUri) {
      Alert.alert('Error', 'Please enter a filename');
      return;
    }
    try {
      await FileSystem.deleteAsync(fileUri);
      setContent('');
      Alert.alert('Success', 'File deleted successfully');
    } catch (e) {
      Alert.alert('Error', 'Failed to delete file');
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Filename:</Text>
      <TextInput
        style={styles.input}
        value={filename}
        onChangeText={setFilename}
        placeholder="Enter filename"
        accessibilityLabel="Filename input"
      />
      <Text style={styles.label}>Content:</Text>
      <TextInput
        style={styles.textArea}
        value={content}
        onChangeText={setContent}
        placeholder="Enter file content"
        multiline
        accessibilityLabel="File content input"
      />
      <View style={styles.buttonRow}>
        <Button title="Save" onPress={saveFile} />
        <Button title="Read" onPress={readFile} />
        <Button title="Delete" onPress={deleteFile} />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, padding: 20, backgroundColor: '#fff' },
  label: { fontSize: 16, marginBottom: 4 },
  input: { borderWidth: 1, borderColor: '#ccc', padding: 8, marginBottom: 12, borderRadius: 4 },
  textArea: { borderWidth: 1, borderColor: '#ccc', padding: 8, height: 100, textAlignVertical: 'top', borderRadius: 4 },
  buttonRow: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 12 }
});

We use Expo's FileSystem API to handle file operations in the app's document directory. The getFileUri function builds the full path for the file using the filename input. The saveFile function writes the content to this file path. The readFile function reads the file content and updates the content state to show it in the text area. The deleteFile function removes the file and clears the content. Each function shows an alert to inform the user about success or failure. Buttons are connected to these functions to trigger the actions. Accessibility labels are added for screen readers. The UI uses simple inputs and buttons arranged vertically with spacing.

Final Result
Completed Screen
-------------------------
|      File Manager      |
-------------------------
| Filename: [myfile.txt] |
|                       |
| Content:               |
| [Hello, this is a     ]|
| [sample file content. ]|
| [                    ] |
|                       |
| [Save] [Read] [Delete]|
-------------------------
User types a filename and content.
Tapping Save writes the content to a file and shows a success alert.
Tapping Read loads the file content into the text area and shows a success alert.
Tapping Delete removes the file and clears the content with a success alert.
If filename is empty, alerts prompt user to enter a filename.
Stretch Goal
Add a button to list all files in the document directory and display their names below.
💡 Hint
Use FileSystem.readDirectoryAsync(FileSystem.documentDirectory) to get file list and show it in a scrollable list.

Practice

(1/5)
1. What is the main purpose of using react-native-fs in a React Native app?
easy
A. To read and write files on the device's file system
B. To create user interface components
C. To manage app navigation between screens
D. To handle network requests and API calls

Solution

  1. Step 1: Understand the role of react-native-fs

    This library is designed to provide file system access in React Native apps.
  2. Step 2: Identify the correct functionality

    It allows reading and writing files on the device, unlike UI or network libraries.
  3. Final Answer:

    To read and write files on the device's file system -> Option A
  4. Quick Check:

    File system access = read/write files [OK]
Hint: Remember: react-native-fs is for file operations only [OK]
Common Mistakes:
  • Confusing file system access with UI components
  • Thinking it manages navigation or network calls
  • Assuming it handles permissions automatically
2. Which of the following is the recommended ES6 import syntax for react-native-fs in a React Native file?
easy
A. import * as RNFS from 'react-native-fs';
B. import RNFS from 'react-native-fs';
C. import { RNFS } from 'react-native-fs';
D. const RNFS = require('react-native-fs');

Solution

  1. Step 1: Recall ES6 import syntax for default exports

    react-native-fs exports a default object, so use import RNFS from 'react-native-fs';.
  2. Step 2: Check other options

    const RNFS = require('react-native-fs'); uses CommonJS require (valid but less common in modern React Native). import { RNFS } from 'react-native-fs'; incorrectly destructures. import * as RNFS from 'react-native-fs'; imports all as namespace but is not the recommended style here.
  3. Final Answer:

    import RNFS from 'react-native-fs'; -> Option B
  4. Quick Check:

    Default import syntax = import RNFS from 'react-native-fs'; [OK]
Hint: Use default import for react-native-fs: import RNFS from '...' [OK]
Common Mistakes:
  • Using destructuring import for default export
  • Mixing require and import styles
  • Using namespace import unnecessarily
3. What will the following code output if the file test.txt contains the text "Hello World"?
import RNFS from 'react-native-fs';

RNFS.readFile(RNFS.DocumentDirectoryPath + '/test.txt', 'utf8')
  .then(contents => console.log(contents))
  .catch(err => console.log('Error:', err.message));
medium
A. Error: File not found
B. An empty string
C. undefined
D. "Hello World"

Solution

  1. Step 1: Understand readFile behavior

    The readFile method reads the file content as a string when encoding is 'utf8'.
  2. Step 2: Check file content and output

    The file contains "Hello World", so the promise resolves and logs this string.
  3. Final Answer:

    "Hello World" -> Option D
  4. Quick Check:

    readFile with utf8 returns file text [OK]
Hint: readFile with 'utf8' returns file text content [OK]
Common Mistakes:
  • Assuming readFile returns a buffer or object
  • Expecting error if file exists
  • Ignoring promise and expecting synchronous output
4. Identify the error in this code snippet that tries to write text to a file:
import RNFS from 'react-native-fs';

RNFS.writeFile('/path/to/file.txt', 'Sample text', 'utf8')
  .then(() => console.log('File written'))
  .catch(error => console.log('Write error:', error));
medium
A. The file path should use RNFS.DocumentDirectoryPath or similar, not an absolute string
B. The encoding 'utf8' is not supported by writeFile
C. writeFile does not return a promise
D. The text argument must be an object, not a string

Solution

  1. Step 1: Check file path usage

    In React Native, absolute paths like '/path/to/file.txt' are invalid; use RNFS.DocumentDirectoryPath or similar directory constants.
  2. Step 2: Validate other parameters

    Encoding 'utf8' is valid, writeFile returns a promise, and text can be a string.
  3. Final Answer:

    The file path should use RNFS.DocumentDirectoryPath or similar, not an absolute string -> Option A
  4. Quick Check:

    Use RNFS paths, not absolute strings [OK]
Hint: Always use RNFS directory constants for file paths [OK]
Common Mistakes:
  • Using absolute file paths directly
  • Misunderstanding writeFile return type
  • Passing wrong data types for text
5. You want to save user notes in a file and then read them back later. Which approach correctly handles permissions, writes the file, and reads it back safely in React Native using react-native-fs?
hard
A. Use fetch API to write and read files on device storage
B. Write file directly to '/storage/emulated/0/notes.txt' without permission, then read it
C. Request storage permission, write file using RNFS.DocumentDirectoryPath, then read file with error handling
D. Write file with no encoding specified, then read file with 'ascii' encoding

Solution

  1. Step 1: Handle permissions properly

    On mobile devices, storage permission must be requested before file operations.
  2. Step 2: Use safe file paths and encoding

    Use RNFS.DocumentDirectoryPath for file location and specify encoding like 'utf8' for writing and reading.
  3. Step 3: Implement error handling

    Use promises with then and catch to handle success and errors safely.
  4. Final Answer:

    Request storage permission, write file using RNFS.DocumentDirectoryPath, then read file with error handling -> Option C
  5. Quick Check:

    Permissions + RNFS paths + error handling = Request storage permission, write file using RNFS.DocumentDirectoryPath, then read file with error handling [OK]
Hint: Always request permission and use RNFS paths with error handling [OK]
Common Mistakes:
  • Skipping permission requests
  • Using hardcoded absolute paths
  • Ignoring promise errors
  • Using wrong encoding for text files
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