---
title: React Native
pagination_prev: demos/static/index
pagination_next: demos/desktop/index
sidebar_position: 1
sidebar_custom_props:
  summary: React + Native Rendering
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
from the main `App.js` entrypoint or any script in the project.
The "Complete Example" creates an app that looks like the screenshots below:
  | iOS | Android | 
|  |  | 
["Fetching Remote Data"](#fetching-remote-data) uses the built-in `fetch` to
download and parse remote workbook files.
["Native Libraries"](#native-libraries) uses native libraries to read and write
files in the local device.
:::caution
**Before reading this demo, follow the official React Native CLI Guide!**
Development Environment Guide: 
Follow the instructions for iOS (requires macOS) and for Android. They will
cover installation and system configuration. You should be able to build and run
a sample app in the Android and the iOS (if applicable) simulators.
:::
## Fetching Remote Data
:::info
React Native `0.72.0` will support binary data with `fetch`. For older versions,
[a native library](#native-libraries) can provide support.
:::
React Native 0.72.0 will support binary data with `fetch`:
```js
/* fetch data into an ArrayBuffer */
const ab = await (await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
/* parse data */
const wb = XLSX.read(ab);
```
### Fetch Demo
The following demo uses `react-native-table-component` to display the first
worksheet in a simple table.
:::note
This demo was tested on an Intel Mac on 2023 April 24 with RN `0.72.0-rc.1`.
The iOS simulator runs iOS 16.2 on an iPhone SE (3rd generation).
:::
1) Create project:
```bash
npx react-native init SheetJSRNFetch --version="0.72.0-rc.1"
```
2) Install shared dependencies:
```bash
cd SheetJSRNFetch
curl -LO https://oss.sheetjs.com/assets/img/logo.png
npm i -S https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz
npm i -S react-native-table-component@1.2.0 @types/react-native-table-component
```
Refresh iOS project by running `pod install` from the `ios` subfolder:
```bash
cd ios; pod install; cd ..
```
3) Download [`App.tsx`](pathname:///reactnative/App.tsx) and replace:
```bash
curl -LO https://docs.sheetjs.com/reactnative/App.tsx
```
**iOS Testing**
Start the iOS emulator:
```bash
npx react-native run-ios
```
When opened, the app should look like the "Before" screenshot below.  After
tapping "Import data from a spreadsheet", the app should show new data:
  | Before | After | 
|  |  | 
**Android Testing**
Start the Android emulator:
```bash
npx react-native run-android
```
:::note
When this demo was last tested, the simulator failed with the message
> Unable to load script.  Make sure you're either Running Metro ...
The workaround is to launch Metro directly:
```bash
npx react-native start
```
Press `a` in the terminal window and Metro will try to reload the app.
:::
When opened, the app should look like the "Before" screenshot below.  After
tapping "Import data from a spreadsheet", the app should show new data:
  | Before | After | 
|  |  | 
## Native Libraries
:::warning
React Native does not provide a native file picker or a method for reading and
writing data from documents on the devices. A third-party library must be used.
Since React Native internals change between releases, libraries may only work
with specific versions of React Native.  Project documentation should be
consulted before picking a library.
:::
The following table lists tested file plugins.  "OS" lists tested platforms
("A" for Android and "I" for iOS).  "Copy" indicates whether an explicit copy
is needed (file picker copies to cache directory and file plugin reads cache).
| File system Plugin         | File Picker Plugin             |  OS  | Copy |
|:---------------------------|:-------------------------------|:----:|:-----|
| `react-native-file-access` | `react-native-document-picker` | `AI` |      |
| `react-native-blob-util`   | `react-native-document-picker` | `AI` | YES  |
| `rn-fetch-blob`            | `react-native-document-picker` | `AI` | YES  |
| `react-native-fs`          | `react-native-document-picker` | `AI` | YES  |
| `expo-file-system`         | `expo-document-picker`         | ` I` | YES  |
### RN File Picker
The following libraries have been tested:
#### `react-native-document-picker`
Selecting a file (click to show)
When a copy is not needed:
```js
import { pickSingle } from 'react-native-document-picker';
const f = await pickSingle({allowMultiSelection: false, mode: "open" });
const path = f.uri; // this path can be read by RN file plugins
```
When a copy is needed:
```js
import { pickSingle } from 'react-native-document-picker';
const f = await pickSingle({allowMultiSelection: false, copyTo: "cachesDirectory", mode: "open" });
const path = f.fileCopyUri; // this path can be read by RN file plugins
```
Selecting a file (click to show)
When using `DocumentPicker.getDocumentAsync`, enable `copyToCacheDirectory`:
```js
import * as DocumentPicker from 'expo-document-picker';
const result = await DocumentPicker.getDocumentAsync({
  // highlight-next-line
  copyToCacheDirectory: true,
  type: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
});
const path = result.uri;
```
Reading and Writing snippets (click to show)
The snippets use `rn-fetch-blob`.  To use `react-native-blob-util`, change the
`import` statements to load the module.
_Reading Data_
```js
import * as XLSX from "xlsx";
import RNFetchBlob from 'rn-fetch-blob'; // or react-native-blob-util
const { readFile } = RNFetchBlob.fs;
const res = await readFile(path, 'ascii');
const wb = XLSX.read(new Uint8Array(res), {type:'buffer'});
```
:::caution
On iOS, the URI from `react-native-document-picker` must be massaged:
```js
import { pickSingle } from 'react-native-document-picker';
import RNFetchBlob from 'rn-fetch-blob'; // or react-native-blob-util
const { readFile, dirs: { DocumentDir } } = RNFetchBlob.fs;
const f = await pickSingle({
// highlight-start
  // Instruct the document picker to copy file to Documents directory
  copyTo: "documentDirectory",
// highlight-end
  allowMultiSelection: false, mode: "open" });
// highlight-start
// `f.uri` is the original path and `f.fileCopyUri` is the path to the copy
let path = f.fileCopyUri;
// iOS workaround
if (Platform.OS === 'ios') path = path.replace(/^.*\/Documents\//, DDP + "/");
// highlight-end
const res = await readFile(path, 'ascii');
```
:::
_Writing Data_
```js
import * as XLSX from "xlsx";
import RNFetchBlob from 'rn-fetch-blob'; // or react-native-blob-util
const { writeFile, readFile, dirs:{ DocumentDir } } = RNFetchBlob.fs;
const wbout = XLSX.write(wb, {type:'buffer', bookType:"xlsx"});
const file = DocumentDir + "/sheetjsw.xlsx";
const res = await writeFile(file, Array.from(wbout), 'ascii');
```
Reading and Writing snippets (click to show)
_Reading Data_
```js
import * as XLSX from "xlsx";
import { FileSystem } from "react-native-file-access";
const b64 = await FileSystem.readFile(path, "base64");
/* b64 is a Base64 string */
const workbook = XLSX.read(b64, {type: "base64"});
```
_Writing Data_
```js
import * as XLSX from "xlsx";
import { Dirs, FileSystem } from "react-native-file-access";
const DDP = Dirs.DocumentDir + "/";
const b64 = XLSX.write(workbook, {type:'base64', bookType:"xlsx"});
/* b64 is a Base64 string */
await FileSystem.writeFile(DDP + "sheetjs.xlsx", b64, "base64");
```
Reading and Writing snippets (click to show)
_Reading Data_
```js
import * as XLSX from "xlsx";
import { readFile } from "react-native-fs";
const bstr = await readFile(path, "ascii");
/* bstr is a binary string */
const workbook = XLSX.read(bstr, {type: "binary"});
```
_Writing Data_
```js
import * as XLSX from "xlsx";
import { writeFile, DocumentDirectoryPath } from "react-native-fs";
const bstr = XLSX.write(workbook, {type:'binary', bookType:"xlsx"});
/* bstr is a binary string */
await writeFile(DocumentDirectoryPath + "/sheetjs.xlsx", bstr, "ascii");
```
Reading and Writing snippets (click to show)
_Reading Data_
Calling `FileSystem.readAsStringAsync` with `FileSystem.EncodingType.Base64`
encoding returns a promise resolving to a string compatible with `base64` type:
```js
import * as XLSX from "xlsx";
import * as FileSystem from 'expo-file-system';
const b64 = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64 });
const workbook = XLSX.read(b64, { type: "base64" });
```
_Writing Data_
The `FileSystem.EncodingType.Base64` encoding accepts Base64 strings:
```js
import * as XLSX from "xlsx";
import * as FileSystem from 'expo-file-system';
const b64 = XLSX.write(workbook, {type:'base64', bookType:"xlsx"});
/* b64 is a Base64 string */
await FileSystem.writeAsStringAsync(FileSystem.documentDirectory + "sheetjs.xlsx", b64, { encoding: FileSystem.EncodingType.Base64 });
```