I am new to react native. I am trying to save signature Image but the function is not even calling. I think its Icon on press issue but when I do console.log on onPress then Its working fine. I think something wrong in function. please help. thanks
here is code.
import SignatureCapture from 'react-native-signature-capture';
this.ref = React.createRef();
this.sign = React.createRef();
saveSign = () => {
this.refs['sign'].saveImage();
};
_onSaveEvent = (result) => {
this.checkAndroidPermission(result);
};
checkAndroidPermission = async (result) => {
if (Platform.OS === 'ios') {
save(result);
} else {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
// Once user grant the permission start downloading
this.save(result);
} else {
if (Platform.OS === 'android') {
ToastAndroid.show('Storage Permission denied.', ToastAndroid.SHORT);
} else {
AlertIOS.alert('Storage Permission denied.');
}
}
} catch (err) {
// To handle permission related exception
console.warn('tryerr', err);
}
}
};
save = async (result) => {
const paths = `${RNFetchBlob.fs.dirs.DCIMDir}/${new Date().getTime()}.png`; // where u need to put that
try {
RNFetchBlob.fs
.writeFile(paths, result.encoded, 'base64') //data.base64 is your photo with convert base64
.then((value) => {
RNFetchBlob.fs
.scanFile([{ path: paths }]) //after save to notify gallry for that
.then(() => {
const file = {
uri:
Platform.OS == 'android'
? 'file://' + paths //path to your file
: paths,
name: 'sign.png', // which go on server on your file name
type: 'image/png', // e.g. 'image/jpg'
};
this.setState({ base64: file });
console.log('scan file success');
console.log('this is fuckiiing file' + JSON.stringify(this.state.base64));
})
.catch((err) => {
console.log('scan file error');
});
})
.catch((e) => console.log(e.message));
} catch (error) {
console.log('fileerror', error.message);
}
};
please ignore this.
I am new to react native. I am trying to save signature Image but the function is not even calling. I think its Icon on press issue but when I do console.log on onPress then Its working fine. I think something wrong in function. please help. thanks I am new to react native. I am trying to save signature Image but the function is not even calling. I think its Icon on press issue but when I do console.log on onPress then Its working fine. I think something wrong in function. please help. thanks
Ok solution is here. just remove this line
saveImageFileInExtStorage={true}
So a few things first, this is very little information to work off, without seeing your views. I'd suggest reading up on how refs work, it's helpful to understand it a little better.
When using refs. You need to use the following syntax to access the object it's pointing to this.refs.current.
Also you create a const ref = React.createRef(); but in the saveSign function you use this.refs maybe a spelling mistake with that variable.
If you are using a Class-based Component using const ref = React.createRef(); is fine. But for a Functional-based Component you should rather use const ref = React.useRef();. Both will work but createRef in a Functional-based Component might cause some undesirable things to happen. useRef is a hook and will work better.
Now some changes I'd make based on my experience, your current code will probably work because it's based on the example from that package but there are better ways of doing it:
I had a look at the example code for the package you are using, which I'm assuming you are using it.
I'd recommend trying to replace the ref inside the <SignatureCapture /> component with this: ref={ref} then inside the saveSign() function calling this.ref.current.saveImage(); rather than this.refs["sign"].saveImage();.
For the <TouchableHighlight> component inside render, rather write your onPress call like this:
onPress={saveSign} and rewriting your saveSign() function like this:
saveSign = () => {
this.ref.current.saveImage();
}
Otherwise, I suggest just debugging why your functions are not being called. It might be an issue with binding some of those functions if you are using a Class-based component.
Related
I know there are plenty of answers related to this topic but I've tried all of them, using useEffect, and it still doesn't work. What I'm trying to do is to update a variable called currentAccount when the app loads and then each time the account changes (this is an app using Metamask).
So when the website loads:
useEffect(() => {
if (!walletConnected) {
[...]
onPageLoad();
}
}, [walletConnected,currentAccount]);
Then, as can be seen, I connect to the connect, select the role of the user logged and there is a listener Metamask provides that listens to an event called 'accountschanged' and when that event is triggered, changes the currentAccount state and again check the role of the new account.
const onPageLoad = async () => {
await connectWallet();
await getUserRole();
window.ethereum.on('accountsChanged', function (accounts) {
setCurrentAccount(accounts[0]);
getUserRole();
})
};
The connectWallet is the one responsible for the first time to update the currentAccount from the default value '' to the current account. The problem is that it doesn't update the value...
const connectWallet = async () => {
// we need to gain access to the provider/signer from Metamask
try {
const provider = await getProviderOrSigner();
let accounts = await provider.send("eth_requestAccounts", []);
setCurrentAccount(accounts[0]);
setWalletConnected(true);
return provider;
} catch (error) {
console.log(error);
}
};
What am I doing bad?? Any idea? I can share with you more code if needed. I know it's a long question but I wanted to give as many details as needed.
Thanks a looott!!!!
Background
I'm building an app which displays a number of stores in the home screen. They are shown in a carousel which is filled up with information from a Firestore Collection and Firebase Storage. The user can navigate into each store by pressing on them. The Home Screen display works just fine every single time, but when navigating to one store components come back as undefined. This is the way I'm fetching the data:
export default function StoreDetailMain ({route}) {
const { storeId } = route.params
const [store, setStore] = useState()
useEffect(() => {
const fetchQuery = async () => {
const storeData = await firebase.firestore()
.collection('stores/')
.doc(storeId)
.get()
.then(documentSnapshot => {
console.log('Store exists: ', documentSnapshot.exists);
if (documentSnapshot.exists) {
console.log('Store data: ', documentSnapshot.data());
setStore(documentSnapshot.data())
console.log(documentSnapshot.data())
}
});
}
fetchQuery()
}, [storeId])
Then I'm rendering the information within tags as in <Text>{store.value}</Text>.
Problem
Navigating once to the store will always return a Component Exception: undefined is not an object (evaluating 'store.value'). However if I cut the "{store.value}" tags it works just fine. Then I can manually type them in again and they render perfectly. Once I go back to the Home Screen and try to go into another store I have to do it all again. Delete the calls for information within the return(), save the code, reload the app and type them in again.
What I have tried
Sometimes, not always, Expo will give me a warning about not being able to perform a React state update on an unmounted component. I thought this might be the problem so I gave it a go by altering my useEffect method:
export default function StoreDetailMain ({route}) {
const { storeId } = route.params
const [store, setStore] = useState()
useEffect(() => {
let mounted = true;
if(mounted){
const fetchQuery = async () => {
const storeData = await firebase.firestore()
.collection('stores/')
.doc(storeId)
.get()
.then(documentSnapshot => {
console.log('Store exists: ', documentSnapshot.exists);
if (documentSnapshot.exists) {
console.log('Store data: ', documentSnapshot.data());
setBar(documentSnapshot.data())
console.log(documentSnapshot.data())
}
});
}
fetchQuery()
}
return () => mounted = false;
}, [storeId])
This would not solve the issue nor provide any variation.
Question
Is this due to the unmounting/mounting of components? If so, wouldn't the useEffect method take care of it? If anyone could provide an explanation/solution it would be very much appreciated.
Thanks in advance.
Edit 1:
When the application fails to render the information, it doesn't print into the console the document snapshot. When it can render the data, it does log it. Thus the change in title.
try giving it a initial value
const [ store, setStore ] = useState({value: ''})
or render it conditionally
{ store?.value && <Text>{store.value}</Text> }
secondly, route.params is defined? When you switching screens, did u make sure u pass the params? Switching from stack navigator to tab navigator for example, may drop the params.
I have tried almost any example provided in docs but I can't run it.
I want to make a request to a specific url with axios (or fetch method) every 60 seconds and process the data in the background. In other words I want something common like:
this.getPageInterval = setInterval(() => {
const json = await (await fetch(this.fetchURL)).json();
...// etc
}, 60000)
can happen when the app is in background.
my console.log says 'task registered' but it feels like this block of code never triggers(global scope):
BackgroundFetch.setMinimumIntervalAsync(5);
const taskName = 'test-background-fetch';
TaskManager.defineTask(taskName, async () => {
console.log('background fetch running');
try {
const receivedNewData = await (await fetch(this.fetchUri)).json();
console.log('receivedNewData', receivedNewData)
return receivedNewData ? BackgroundFetch.Result.NewData : BackgroundFetch.Result.NoData;
let isRegistered = await TaskManager.isTaskRegisteredAsync(taskName);
console.log("isRegistered: ", isRegistered);
} catch (error) {
return BackgroundFetch.Result.Failed;
}
console.log("BackgroundFetch.Result.NewData", BackgroundFetch.Result.NewData);
return BackgroundFetch.Result.NewData;
});
and in my class component:
await BackgroundFetch.registerTaskAsync(taskName, {
setMinimumIntervalAsync: 5,
stopOnTerminate: false
});
await BackgroundFetch.setMinimumIntervalAsync(5);
alert('task registered');
console.log('task registered');
It seems you're not registering your task in your class component. Is taskname defined as 'test-background-fetch' in your component? You need to call exactly the same task name.
Also some phones are somewhat problematic with background tasks. I never tried it on expo, but on React Native some brands had to go through some extra setup.
Also note that in the documentation it says it only works when backgrounded. Terminated apps wont run the background function.
I'm trying to make a scanner in React Native that takes an image file, scans it and returns data that contains in barcode. I'm using a BarCodeScanner extension from Expo SDK.
It throws an error when I'm trying to use it.
Error looks like:
An exception was thrown while calling `ExpoBarCodeScannerModule.scanFromURLAsync` with arguments `(
1,
(
"org.iso.QRCode"
)
)`: -[__NSCFNumber length]: unrecognized selector sent to instance 0xe17787ebcc27c1d0
- node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:104:55 in <unknown>
- node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:414:4 in __invokeCallback
- ... 4 more stack frames from framework internals
My code where I'm trying to use extension method:
file = require('./assets/image.jpg');
componentDidMount(){
BarCodeScanner.scanFromURLAsync(this. file).then(data => {
console.log(data)
}).catch(err => {
console.log(err)
})
}
Do you have any thoughts what does it mean?
A bit too late, but for anyone with simmilar problem. You can use expo ImagePicker package to select image. It will return array of objects. One of the parameters of the object is URI of the image that can be used as an input to BarCodeScanner.scanFromURLAsync method.
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
allowsEditing: false,
quality: 1,
});
if (!result.canceled) {
let decodedBarcodeImage = await BarCodeScanner.scanFromURLAsync(result.assets[0].uri);
// Handle result data
console.log(decodedBarcodeImage);
} else {
// Handle canceled result
console.log('You did not select any image.');
}
};
I'm currently using the expo camera in my application on iOS.
The app crashes when I try to save the image like this.
takePicture = async function() {
this.camera.takePictureAsync().then(data => {
FileSystem.moveAsync({
from: data,
to: `${FileSystem.documentDirectory}photos/Photo_${this.state
.photoId}.jpg`,
}).then(() => {
this.setState({
photoId: this.state.photoId + 1,
});
Vibration.vibrate();
}).catch((err) => {
console.log("Error : " + err);
});
}).catch(error => {
console.log(error);
});
Vibration.vibrate();
console.log("Taking pic");
}
In addition the Vibration.vibrate() doesn't actually vibrate the phone. I receive an error earlier in the execution here:
componentDidMount() {
FileSystem.makeDirectoryAsync(
FileSystem.documentDirectory + 'photos'
).catch(e => {
console.log(e, 'Directory exists');
});
}
The error just says
[Error: Directory 'file:///var/mobile/Containers/Data/Application/X/Documents/ExponentExperienceData/X/photos' could not be created.]
Is there anyone else who has experienced the same issue? If anyone is able to let me know how to add the vibration too this would be fantastic. I've added it in the top of the file as:
import {
StyleSheet,
Text,
View,
TouchableOpacity,
Slider,
Image,
Picker,
Button,
ScrollView,
Vibration,
} from 'react-native';
EDIT: I've solved the issue with saving to the cameraroll. The issue with the vibration still stands.
Thanks
For the first problem you describe, although you solved it via a workaround by saving it to cameraroll, I would suggest you post the edited code to keep the question correctly up to date.
FileSystem Issue
Addressing the FileSystem error issue, the original code should work as it is, but you could check:
If the expo app has appropriate file access permissions (should be automatic via the expo library, but try updating the expo app). Documentation on FileSystem can be found here: https://docs.expo.io/versions/latest/sdk/filesystem.html
You may need to create the intermediate directories (i.e. photos):
like this:
async componentDidMount() {
try {
await FileSystem.makeDirectoryAsync(
`${FileSystem.documentDirectory}photos`,
{
intermediates: true, // creates intermediate directories
}
)
} catch (e) {
console.log(e)
}
}
Vibration Issue
The vibration problem is probably caused by a bug in react-native as described here: https://github.com/facebook/react-native/issues/8955#issuecomment-353373616
As a workaround you could vibrate before setting the state i.e:
takePicture = async function() {
if (this.camera) {
const picture = await this.camera.takePictureAsync();
const pictureFile = await FileSystem.moveAsync(
{
from: picture.uri,
to: `${
FileSystem.documentDirectory
}photos/Photo_${this.state.photoId}.jpg`
}
).catch(err => console.error(err));
Vibration.vibrate();
console.log("Pic taken", this.state.photoId);
return this.setState({
photoId: this.state.photoId + 1
});
}
};