I have been trying to open a pdf file using react native, but every library that I try generates an error. I tried the code below:
import React, { Component } from 'react';
import Pdf from 'react-native-pdf';
class OpenBGReport extends Component {
render() {
const source = {uri:'http://samples.leanpub.com/thereactnativebook-sample.pdf',cache:true};
return (
<View style={styles.container}>
<Pdf
source={source}
onLoadComplete={(numberOfPages,filePath)=>{
console.log(`number of pages: ${numberOfPages}`);
}}
onPageChanged={(page,numberOfPages)=>{
console.log(`current page: ${page}`);
}}
onError={(error)=>{
console.log(error);
}}
style={styles.pdf}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
marginTop: 25,
},
pdf: {
flex:1,
width:Dimensions.get('window').width,
height:Dimensions.get('window').height,
}
});
export default OpenBGReport;
However, after installing react-native-pdf, my project stop working and returns: null is not an object (evaluating 'rnfetchblob.documentdir')
What is the best way to open and display a pdf from a URL in react native?
Thanks
Expo doesn't support installing native modules and react-native-pdf is a native module. Possible solutions:
If you really want to use native modules, you should use react-native-cli or eject expo project. You can find a more detailed answer in the repository FAQ section (https://github.com/wonday/react-native-pdf#faq).
You can always open PDF files in the phone browser by using react-native's Linking API.
There is a package to display PDF files in expo projects (https://github.com/xcarpentier/rn-pdf-reader-js). Never used the package, and it also seems very sketchy as it supports only the Android platform, and on iOS, you would need to use WebView to display pdf. Also, it doesn't have a lot of downloads on npm and the project itself is prettry stale.
You can use <WebView/> from "react-native-webview" (https://github.com/react-native-webview/react-native-webview)
I tested this one on ios with expo, and it's work!
<WebView
originWhitelist={['*']}
source={{uri: uri}}
url can be a web link or path to your file local ('file:///...')
The best way I found to handle PDF files with Expo is to use buffer to turn them into base64 files, store them in the FileSystem and Share them:
import { Buffer } from "buffer";
import * as FileSystem from "expo-file-system";
import * as Sharing from "expo-sharing";
res = await // fetch PDF
const buff = Buffer.from(res, "base64");
const base64 = buff.toString("base64");
const fileUri =
FileSystem.documentDirectory + `${encodeURI("name-of-the-pdf")}.pdf`;
await FileSystem.writeAsStringAsync(fileUri, base64, {
encoding: FileSystem.EncodingType.Base64,
});
Sharing.shareAsync(res);
Note: You need to install buffer, expo-file-system and expo-sharing
Related
I'm trying to render svg file path from #dicebear/avatars
let svg = createAvatar(style, {
seed: 'random',
// ... and other options
});
svg variable has this value =
But when i try to render in react-native is not showing even if i use a library called react-native-render-html
I'm trying to render using the library like this
<View style={styles.container}>
<HTML source={{ html: svg }} />
<StatusBar style="white" />
</View>
When i do this this is what i get[
You can do this using react-native-svg.
Steps:
Install the library using npm install react-native-svg
Rebuild the app after clearing the cache.
Now use the XML like
import React from 'react';
import {createAvatar} from '#dicebear/avatars';
import * as style from '#dicebear/avatars-identicon-sprites';
import {SvgCss} from 'react-native-svg';
const xml = createAvatar(style, {
seed: 'custom-seed',
});
export default function App() {
return <SvgCss xml={xml} width="100%" height="100%" />;
}
When internet access is on, useAssets returns the localUri as expected. But after going offline, it returns undefined. Even the cached file still exists in the cache folder, it does not reference it. The code is below:
import React from "react";
import { useAssets } from "expo-asset";
import { Image, View } from "react-native";
export default function Avatar({ imageUrl}) {
const [assets, error] = useAssets([imageUrl]);
return (
<View style={[styles.avatar, style]}>
<Image
source={{
uri: assets[0].localUri
}}
/>
</View>
);
}
So I want to access downloaded and cached images offline with useAssets hook but it seems that expo-assets has not such feature, isn't it?
You need to install the 'expo-asset' package.
expo install expo-asset
I have seen this issue posted on stack overflow many times with no clear answer. I'm hoping this question can help me and others out.
I wish to render a URL in react native using react-native-webview
I started a blank react native project using expo init my-app. I ran npm i react-native-webview and react-native link react-native-webview. I then created a file defined as the following
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
class WebViewTest extends Component {
render() {
return (
<WebView
source={{ uri: 'https://www.google.com/' }}
style={{ marginTop: 20, width: 400, height: 400 }}
/>
);
}
}
export default WebViewTest;
My app.js imports and renders that file like the following
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import WebViewTest from './Components/WebViewTest';
export default function App() {
return (
<WebViewTest />
);
}
I test this code by running expo start and I open up my project in a web browser.
I then see the following in the browser
I don't get any errors or warnings so where am I going wrong?
As Per The Expo Docs For WebView -
https://docs.expo.io/versions/latest/sdk/webview/
https://www.npmjs.com/package/react-native-webview
It Doesn't Work On Web Using EXPO
I have an Expo app using the Managed workflow. The app needs to check whether an internet connection is available.
I can't import { NetInfo } from 'react-native' because that's deprecated.
I can't use react-native-community/react-native-netinfo because that uses native libraries, and you can't do that with an Expo managed app.
I could eject, in order to use the above, but it doesn't seem like I should need to do that just to check if there's an internet connection.
I can't use navigator.onLine because that global variable doesn't seem to be available.
I could make a trivial HTTP request to Google or my own server or whatever, and see if I get a response, but that only tests a connection to one site, and also it takes time and uses bandwidth.
What should I do?
Expo SDK 34 has already included NetInfo API.
You can check their documentation for SDK 34 here https://docs.expo.io/versions/v34.0.0/sdk/netinfo
Here is the link for documentation for latest version
Use NetInfo of react-native.
Yes, it is deprecated because they are planning on removing it in the next version of react-native in favor of the community version. However, it is completely functional and can still be used for now, just make sure to check for breaking changes when the next versions of Expo SDK are released.
It is likely that Expo will bring it into their managed workflow when react-native removes it, or provide an alternative that won't require ejecting from Expo.
It's really hard to define if a device has internet or not stackoverflow.com/a/189443/7602110, just by having failed XHR requests you can say that you have internet, but isn't that reliable. You would like to check with some reliables websites like google.com, I have come with a work-around but I don't actually recommend it, is up to you.
You can use the Linking.canOpenUrl() method from React Native itself, which will return a Promise object. When it is determined whether or not the given URL can be handled, the promise is resolved and the first parameter is whether or not it can be opened.
Then add a request and if the response status it's 200 you should have internet.
import React, { Component } from 'react';
import { Button, Text, View, StyleSheet, Linking } from 'react-native';
export default class App extends Component {
state = {
connection: false,
url: 'https://google.com',
};
checkInternt = () => {
Linking.canOpenURL(this.state.url).then(connection => {
if (!connection) {
this.setState({ connection: false });
} else {
fetch(this.state.url).then(res =>
this.setState({ connection: res.status !== 200 ? false : true })
);
}
});
};
componentDidMount() {
this.checkInternt();
}
handlePress = () => {
this.setState({
url:
this.state.url === 'https://google.com'
? 'http://someweirdurlthatdoesntwork.com'
: 'https://google.com',
});
this.checkInternt();
};
render() {
return (
<View style={styles.container}>
<Text>
Connection:
<Text style={{ color: this.state.connection ? 'green' : 'red' }}>
{` ${this.state.connection}`}
</Text>
</Text>
<Text>{this.state.url.replace(/\https?:\/\//g, '')}</Text>
<Button onPress={this.handlePress} title="Change server url" />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-around',
alignItems: 'center',
},
});
Check the snack: snack.expo.io/#abranhe/check-internet
2022 here, had the same issue before ejecting expo, we used expo-network
import * as Network from 'expo-network';
and use it like so
const networkState = await Network.getNetworkStateAsync();
I hope this helps someone!
It is the first time that I write that kind of question here so please excuse me if my question is not okay.
I am learning some new cross platform frameworks. I am interesting in Ionic(version 4), Flutter, React Native and NativeScript. Precisely, I would like to understand the concept of code reusability for each framework. How do they apply reusability? In which matrix and what are the consequences?
Thanks.
In react-native you have create any component used any screen. for example I used InputText component for reusability.
InputField.js
import React, { Component } from "react";
import { TextInput, View, StyleSheet, Text,Image } from "react-native";
export class InputField extends Component {
render() {
const {
textentry,
keytype,
isvalid,
errormsg,
returnkey,
textplaceholder,
underlinecolor,
onchangetext
} = this.props;
return (
<View>
<TextInput
style={styles.input}
placeholder={textplaceholder}
keyboardType={keytype}
placeholderTextColor="#ffffff"
underlineColorAndroid={underlinecolor}
secureTextEntry={textentry}
ref={(input) => this.props.inputRef && this.props.inputRef(input)}
returnKeyType={returnkey}
blurOnSubmit={false}
onSubmitEditing={(event) => {
if (returnkey != 'done') {
this.props.onSubmitEditing(event)
}
}}
onChangeText={text => {
this.props.onText(text);
}}
/>
<View>
{!isvalid ? (
<Text style={styles.errormsg}>{errormsg}</Text>
) : null}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
input: {
width: 300,
color: "#ffffff",
justifyContent: "center",
alignItems: "center",
alignSelf: "center"
},
errormsg: {
color: "#ff0000",
marginLeft: 60
},
});
export default InputField;
Use this InputField component to screen
Myscreen.js
import React, { Component } from "react";
import {
View,
StyleSheet
} from "react-native";
import { InputField } from "../component/InputField";
render() {
return (
<View style={{flex:1}}>
<InputField
keytype="default"
textplaceholder="Enter First Name"
textentry={false}
returnkey="next"
isvalid={this.state.firstNameValid}
errormsg={this.state.errormsgtext}
underlinecolor={this.state.underLineColorFirstName}
onText={text => {
this.setState({ firstName: text });
}}
onSubmitEditing={event => {
this.inputs["phone"].focus();
}}
/>
</View>
)}}
About React Native, it works with something called Components. You may create a component for each thing you could imagine. The best of having components is that they are reusables. For example, I can create a button in a component and then export that same button to other apps or screens.
Talking about code sharing between Web and Mobile regarding NativeScript here are a few things to know:
Disclaimer: I am part of the NativeScript team
First it is only possible via Angular, there is not code sharing if you prefer to use pure JS or TypeScript
Second the portion of the code shared between the Web, iOS and Android is dependant on the functionality of your app. Meaning that if you rely heavily on platform specific functionality both for the UI and the code behind logic it is possible to not be able achieve full code shared, yet there are ways to overcome such scenarios and again be able to share common services.
Third the idea of code sharing with NativeScript is that if you have a specific code for a "platform" (Web, iOS and/or Android) you simply create additional file with a specific file name. For example if you have an Angular component named home.component.ts you should have one file containing its HTML for the Web part and one for the Mobile part so you simply create both home.component.html and home.component.tns.html. Similar approach is used for other non component files like css and angular services etc.
The technique that is used to achieve code sharing in NativeScript with Web is with the use of Angular schematics specifically for NativeScript.
The topic of exactly how code sharing is achieve is quite log so I would suggest you to read this blog post that introduces the code sharing between Web, iOS and Android with NativeSript. For a getting started steps I recommend the official documentation here.