I’m trying to implement a ReadScreen component for my app that uses the epubjs-react-native library to open an epub given a URI of a file that’s on my machine.
I’m running into a strange error. When I dynamically set the URI using a document picker, and then pass that picked URI as a state variable to the Reader component from epubjs-react-native, it works great. (I’ll explain the flow soon)
However, when I retrieve that same URI I’m passing as a state variable (by logging it on the console and copying it) and then paste that as the src prop to the Reader component, it doesn’t work, and I get “opening…” showing on my screen for a very long time.
I’m wondering what the difference between passing a picked URI from a file state variable and the actual uri is, and how I can get the reader to work with an actual uri.
So, here’s the working code that uses the picker:
import React, {useState} from "react";
import { View, Button } from "react-native";
import { ReaderProvider } from "@epubjs-react-native/core";
import * as DocumentPicker from "expo-document-picker";
import { Reader } from "@epubjs-react-native/core";
import { useFileSystem } from "@epubjs-react-native/expo-file-system";
export default function ReadScreen() {
const [fileUri, setFileUri] = useState(null);
const pickDocument = async () => {
try {
const res = await DocumentPicker.getDocumentAsync({
type: "application/epub+zip",
copyToCacheDirectory: false,
});
if (res.assets && res.assets.length > 0) {
setFileUri(res.assets[0].uri);
} else {
setFileUri(null);
console.log("No file selected");
}
} catch (err) {
console.log("Error while picking the file", err);
}
};
if (fileUri){
return (
<ReaderProvider>
<Reader src={fileUri} fileSystem={useFileSystem} />
</ReaderProvider>
);
} else {
return (
<View >
<Button
title="Pick an epub file"
onPress={pickDocument}
/>
</View>
);
}
}
How this works:
There is a state variable called “fileUri” initialized to null. Depending on whether this variable is defined or null, the component renders two different things.
If fileUri null, it renders a button is used to call “pickDocument”. PickDocument uses the DocumentPicker from Expo, gets a response and sets fileUri to the uri of the response object.
If fileUri is not null, it renders a Reader component with “src” set to fileUri.
So the flow is:
1) fileUri is null
2) A button is rendered
3) Button pressed opens the document picker
4) If a valid file is selected, fileUri gets set and is no longer null
5) Reader gets called rendered the fileUri set as src.
Now, my objective is to be able to use a hardcoded URI from my device and render a Reader component with that URI. So how do I get the URI? I log it! (I add the following hook:)
Summary
I’m trying to implement a ReadScreen component for my app that uses the epubjs-react-native library to open an epub given a URI of a file that’s on my machine.
I’m running into a strange error. When I dynamically set the URI using a document picker, and then pass that picked URI as a state variable to the Reader component from epubjs-react-native, it works great. (I’ll explain the flow soon)
However, when I retrieve that same URI I’m passing as a state variable (by logging it on the console and copying it) and then paste that as the src prop to the Reader component, it doesn’t work, and I get “opening…” showing on my screen for a very long time.
I’m wondering what the difference between passing a picked URI from a file state variable and the actual uri is, and how I can get the reader to work with an actual uri.
So, here’s the working code that uses the picker:
How this works:
There is a state variable called “fileUri” initialized to null. Depending on whether this variable is defined or null, the component renders two different things.
If fileUri null, it renders a button is used to call “pickDocument”. PickDocument uses the DocumentPicker from Expo, gets a response and sets fileUri to the uri of the response object.
If fileUri is not null, it renders a Reader component with “src” set to fileUri.
So the flow is:
1) fileUri is null
2) A button is rendered
3) Button pressed opens the document picker
4) If a valid file is selected, fileUri gets set and is no longer null
5) Reader gets called rendered the fileUri set as src.
Now, my objective is to be able to use a hardcoded URI from my device and render a Reader component with that URI. So how do I get the URI? I log it! (I add the following hook:)
This is what I get on the console:
file:///private/var/mobile/Containers/Data/Application/45FF978B-313D-4160-8D88-28E588F5F85B/tmp/host.exp.Exponent-Inbox/Aldous%20Huxley%20-%20Brave%20New%20World-Harper%20Perennial%20Modern%20Classics%20(2010).epub
Now, it would make sense that if I use this URI by just setting it for “src” in the Reader component, it would yield exactly the same result.
But this yields an infinite spinner that says “Opening” below it.
What platform(s) does this occur on?
iOS
What workflow(s) does this occur on?
Expo Workflow
Environment (or package.json)
{ "name": "screens", "version": "1.0.0", "main": "expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@epubjs-react-native/core": "^1.4.5", "@expo/vector-icons": "^14.0.2", "@types/react": "~18.2.79", "expo": "~51.0.14", "expo-document-picker": "^12.0.2", "expo-file-system": "^17.0.1", "expo-status-bar": "~1.12.1", "openai": "^4.51.0", "react": "18.2.0", "react-native": "0.74.2", "react-native-gesture-handler": "^2.17.0", "react-native-webview": "^13.10.3", "typescript": "~5.3.3",
}, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }
Your .epub file
No response
Minimal reproducible example
No response
I confirm that i have