React Native websockets with hooks INVALID_STATE_ERR - react-native

React Native wont send multiple messages on state change throught websocket. Server recives 1st string normally and client gets console logs on every state change. Any idea why I get an error about state?
useEffect(() => {
socket.onopen = function (e) {
socket.send(String(state?.x));
};
socket.send("test") <-- this one does not work
console.log("send")
socket.onmessage = function () {
console.log("message")
}
socket.close();
}, [state])
Returns error INVALID_STATE_ERR

So basically when using react native with EXPO you will get those errors. After the application is build and installed (on the same phone) the application works.

Related

WalletConnect React Native - No events fired

I'm having a hard time getting WalletConnect 1.7.7 to work on React Native. I want to integrate in a crypto Wallet to handle dapps requests. Their documentation is...lacking. I'm following the "quickstart" in their docs, but listeners never gets fired.
import WalletConnect from "#walletconnect/client";
// Create connector
const connector = new WalletConnect(
{
// Required
uri: "wc:8a5e5bdc-a0e4-47...TJRNmhWJmoxdFo6UDk2WlhaOyQ5N0U=",
// Required
clientMeta: {
description: "WalletConnect Developer App",
url: "https://walletconnect.org",
icons: ["https://walletconnect.org/walletconnect-logo.png"],
name: "WalletConnect",
},
});
connector.on("session_request", (error, payload) => {
if (error) {
throw error;
}
// Handle Session Request
});
But session_request or any other event never get's fired. As per their documents that's all I need. Is there anything else I'm missing or perhaps it's not documented?
The documentation for Wallet Connect is very incomplete and there is very little information on the web. Are you using React Native with Expo? Because there the implementation changes. I don't see any flaws in your code. Test your integration from this website https://example.walletconnect.org/.
Using connect event instead of session_request on walllet connect works for me in react native.
connector.on('connect',(error,payload)=>{
console.log('eventtt',payload)
// Alert.alert('Connected')
})

useURL hook expo-linking for background app

The expo-linking React Native package has a hook named useURL that isn't working for me when the app is in the background. From the docs it Returns the initial URL followed by any subsequent changes to the URL. The problem I'm having with my managed expo app is that the hook doesn't work when the app is already open in the background. Here is the hook:
export default function App() {
const isLoadingComplete = useCachedResources();
const url = Linking.useURL();
useEffect(() => {
Alert.alert(url ? url.substring(20) : 'null');
}, [url]);
if (!isLoadingComplete) {
return null;
} else {
return (
...
);
}
}
If I open the URL exp://exp.host/#myprofile/myproject?a=bwhen the app is closed, I get an Alert as expected. If the app is in the background, the Alert doesn't go off. I've tested on an iOS emulator and a physical Android. Any solutions? Note that similar problems happen with Linking.addEventListener().

How to use setTimeout in react native?

Hi I working on a react native project I need to support my app offline.
I used NetInfo Library from expo documentation.
like below
const netInfo = useNetInfo();
const networkCheck = () => {
setTimeout(() => {
const net = netInfo.isInternetReachable;
console.log(net);
if (net === false) {
setloadCachedListings(true);
}
}, 2000);
};
networkCheck();
I want to wait for some time at this step of my code because this hook always returns null first time then after few milliseconds it tells the real network status.
But this code is not working as I an trying to do.
Is there any way to achieve this?
I just want to wait a little bit to get real network connection and then go further with my code.
logs for netInfo hook.

How to force users to update the app using react native

I have updated my app on app and play store and I want to force my app users to update the new version of app in App store and playstore.
You can check for the App Store / Play Store version of your app by using this library
react-native-appstore-version-checker.
In expo app you can get the current bundle version using Constants.nativeAppVersion. docs.
Now in your root react native component, you can add an event listener to detect app state change. Every time the app transitions from background to foreground, you can run your logic to determine the current version and the latest version and prompt the user to update the app.
import { AppState } from 'react-native';
class Root extends Component {
componentDidMount() {
AppState.addEventListener('change', this._handleAppStateChange);
}
_handleAppStateChange = (nextState) => {
if (nextState === 'active') {
/**
Add code to check for the remote app version.
Compare it with the local version. If they differ, i.e.,
(remote version) !== (local version), then you can show a screen,
with some UI asking for the user to update. (You can probably show
a button, which on press takes the user directly to the store)
*/
}
}
componentWillUnmount() {
AppState.removeEventListener('change', this._handleAppStateChange);
}
}
import VersionCheck from 'react-native-version-check';
i have used version check lib for this purpose and approach i used is below. if version is lower i'm opening a modal on which an update button appears, and that button redirects to app store/google play
componentDidMount() {
this.checkAppUpdate();
}
checkAppUpdate() {
VersionCheck.needUpdate().then(res => {
if (res.isNeeded) {
setTimeout(() => {
this.setState({openModal: true});
});
}
});
}
updateApp = () => {
VersionCheck.getStoreUrl({
appID: 'com.showassist.showassist',
appName,
})
.then(url => {
Linking.canOpenURL(url)
.then(supported => {
if (!supported) {
} else {
return Linking.openURL(url);
}
})
.catch(err => console.error('An error occurred', err));
})
.catch(err => {
console.log(`error is: ${err}`);
});
};
For future readers.
If you are using Expo managed workflow, install this package react-native-version-check-expo using yarn add react-native-version-check-expo or npm install react-native-version-check-expo.
Consult the package documentation on Github for usage guidelines.
I'm using react-native-version-check-expo library to achieve this. Working fine for me.
if you are looking for an easy to integrate built in solution. You can use App Upgrade https://appupgrade.dev/ service to force update your mobile apps.
Create new version entry for your app version that you want to update in the app upgrade service and select whether you want to force it or just want to let users know that new version is available.
Integrate your app with App Upgrade using available SDK. Official SDK are available for React Native, Flutter, Expo, Android and iOS(Swift).
The SDK will take care of the rest.
Whenever you want to force upgrade a version just create a version entry in app upgrade dashboard.
You can also integrate using API. Just call the appupgrade api from your app with the required details such as your app version, platform, environment and app name.
The API will return you the details.. that this app needs to be updated or not.
Based on the response you can show popup in your app.You can call this API when app starts or periodically to check for the update. You can even provide a custom message.
API response:
See the response has force update true. So handle in the app by showing popup.
You can find the complete user documentation here. https://appupgrade.dev/docs
Thanks.

How to report different errors in React Native application?

Is there a solution for reporting different errors in React Native application (iOS and Android) as a global handler?
I am interested in following cases:
Unhandled rejections
Unhandled exceptions
Errors on the native side
By reporting, I mean sending them to some third-party service where you can track errors.
In RN there is a ErrorUtils global handler, that handle uncaught and caught exceptions for your RN JS layer. You can use this to set a handler like:
if (ErrorUtils._globalHandler) {
instance.defaultHandler = ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler() || ErrorUtils._globalHandler;
ErrorUtils.setGlobalHandler(instance.wrapGlobalHandler); //feed errors directly to our wrapGlobalHandler function
}
And handler method
async wrapGlobalHandler(error, isFatal){
const stack = parseErrorStack(error);
//Add this error locally or send it your remote server here
//*> Finish activity
setTimeout (() => {
instance.defaultHandler(error, isFatal); //after you're finished, call the defaultHandler so that react-native also gets the error
if (Platform.OS == 'android') {
NodeModule.reload()
}
}, 1000);
}
Notice in above code you need to create a node module for android only and write a React Native bridge method there in your ReactContextBaseJavaModule:
#ReactMethod
public void reload() {
Activity activity = getCurrentActivityInstance();
Intent intent = activity.getIntent();
activity.finish();
activity.startActivity(intent);
}
Thanks!