Send parameters in headers with ActionCable in React Native - react-native

Im stuck trying to create a cable and channel for a chat. Im working in react native and I am consuming a back end made in Ruby on Rails that is expecting my uid in header parameter:
def find_verified_user # this checks whether a user is authenticated with devise
User.find_by(uid: request.headers['HTTP_AUTHORIZATION']) || reject_unauthorized_connection
end
What is happening is thay I get stuck in the reject unauthorized connection.
What i'm trying to figure out is how I can send in react native my headers when I create the cable.
I've googled and look here and most answers say is not possible, but they are from 2016 or 2017 so maybe now it is possible? I see solutions by putting parameters in url as queryparams but in that case I need to change my backend api, so I was wondering if there is another solution without having to change backend.
I'm using ActionCable from 'actioncable'.
I've tryied using ActionCableJwt from 'react-native-action-cable-jwt' but either I'm doing something wrong or it doesn't help in my case.
Thanks in advance. Any help is appreciated.
EDIT: Show some action cable code:
import { Platform } from 'react-native';
import ActionCable from 'actioncable';
import { ANDROID, IOS } from 'constants/common';
ActionCable.getConfig = () => null;
ActionCable.createWebSocketURL = url => url.replace(/^http/, 'ws');
const oldOpen = ActionCable.Connection.prototype.open;
ActionCable.Connection.prototype.open = function open() {
const result = oldOpen.apply(this);
this.webSocket.protocol = 'actioncable-v1-json';
return result;
};
if (Platform.OS === IOS || Platform.OS === ANDROID) {
global.document = {
addEventListener() {},
removeEventListener() {},
};
}
export default ActionCable;
And when I use it (right now with query params instead of headers):
import actionCable from './actionCable';
import { applyQueryParams } from 'utils/helpers';
let cable = null;
return store => next => action => {
switch (action.type) {
case createConsumer.toString(): {
cable?.disconnect();
const { uid } = action.payload;
const queryParams = {
uid,
};
cable = actionCable.createConsumer(
applyQueryParams(Config.CABLE_URL, queryParams),
);

Related

How to use setState with ssdp m-search discovery?

I am using SSDP search message to discover devices with connected same network but when i tried to call setState hooks inside client.on function I only get one device informations.
I initialized my state value in this way
const [deviceList, setDeviceList] = useState([]);
And create a function for the client to add deviceList as it is found
const getAllDevices = () => {
var Client = require('react-native-ssdp-remote').Client,
client = new Client();
client.search('urn:dial-multiscreen-org:service:dial:1');
client.on('response', function (headers) {
const url = new URL(headers.LOCATION);
if (url != null) {
if (!deviceList.includes(url)) {
setDeviceList([...deviceList, url]);
}
}
});
};
and called this function inside useEffect
useEffect(() => {
getAllDevices();
}, []);
There are 4 devices connected to same network and it goes into setDeviceList process 4 times but i can only get one device. Could you please support.
Thanks.
I think this is more of a race condition instead of a library issue.
Give it a try with using functional update on setDeviceList.
setDeviceList(deviceList => {
return [...deviceList, url]
}

How to get the device token in react native

I am using react-native 0.49.3 version, My Question is how to get the device token in react native for both IOS and Android I tried with this link but it not working for me, right now I tried in IOS. how to resolve it can one tell me how to configure?
I tried different solutions and I've decided to use React Native Firebase.
Here you will find everything about Notifications.
Also, you can use the others libraries that come with Firebase, like Analytics and Crash Reporting
After set up the library you can do something like:
// utils/firebase.js
import RNFirebase from 'react-native-firebase';
const configurationOptions = {
debug: true,
promptOnMissingPlayServices: true
}
const firebase = RNFirebase.initializeApp(configurationOptions)
export default firebase
// App.js
import React, { Component } from 'react';
import { Platform, View, AsyncStorage } from 'react-native';
// I am using Device info
import DeviceInfo from 'react-native-device-info';
import firebase from './utils/firebase';
class App extends Component {
componentDidMount = () => {
var language = DeviceInfo.getDeviceLocale();
firebase.messaging().getToken().then((token) => {
this._onChangeToken(token, language)
});
firebase.messaging().onTokenRefresh((token) => {
this._onChangeToken(token, language)
});
}
_onChangeToken = (token, language) => {
var data = {
'device_token': token,
'device_type': Platform.OS,
'device_language': language
};
this._loadDeviceInfo(data).done();
}
_loadDeviceInfo = async (deviceData) => {
// load the data in 'local storage'.
// this value will be used by login and register components.
var value = JSON.stringify(deviceData);
try {
await AsyncStorage.setItem(config.DEVICE_STORAGE_KEY, value);
} catch (error) {
console.log(error);
}
};
render() {
...
}
}
Then you can call the server with the token and all the info that you need.

How to connect React App with Shopify App?

I'm new to shopify-App developmet and came across Polaris, react library provided by Shopify for consistent user-interface development. My ideas is to build a Node.js Express App to authenticate and install the app and to process data and have a react app for the User Interface for the shop-admin.
I searched through the web, but couldn't find a standard or recommended way of connecting react app to the shopify app.
What I could figure out was to redirect to the React app from the Node app when a shop admin select app from Apps section and is authenticated successfully as follow.
app.get('/shopify/callback', (req, res) => {
const { shop, hmac, code, state } = req.query;
const stateCookie = cookie.parse(req.headers.cookie).state;
if (state !== stateCookie) {
return res.status(403).send('Request origin cannot be verified');
}
if (shop && hmac && code) {
const map = Object.assign({}, req.query);
delete map['signature'];
delete map['hmac'];
const message = querystring.stringify(map);
const generatedHash = crypto
.createHmac('sha256', apiSecret)
.update(message)
.digest('hex');
if (generatedHash !== hmac) {
return res.status(400).send('HMAC validation failed');
}
const accessTokenRequestUrl = 'https://' + shop + '/admin/oauth/access_token';
const accessTokenPayload = {
client_id: apiKey,
client_secret: apiSecret,
code,
};
request.post(accessTokenRequestUrl, { json: accessTokenPayload })
.then((accessTokenResponse) => {
const accessToken = accessTokenResponse.access_token;
const shopRequestUrl = 'https://' + shop + '/admin/shop.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
};
res.redirect([URL to the react app built with Polaris]);
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
} else {
res.status(400).send('Required parameters missing');
}
});
I got this working, but I'm not sure whether this is the recommended way to do it.
They are 3 different things: Node.JS, React, and Polaris and you can choose any of them. Polaris is a library and if you want to use it just run yarn add #shopify-polaris and read its documentation. That's all.
With or without Polaris, you could still create a Shopify app, with various stacks.

How Do I use a node.js module with Next.js?

Do I need to use express with next.js?
Im trying to add this code into a next.js application. ( from npm module example code: pdf2json )
let fs = require('fs');
var PDFParser = require("pdf2json");
let pdfParser = new PDFParser(this,1);
pdfParser.on("pdfParser_dataError", errData =>
console.error(errData.parserError) );
pdfParser.on("pdfParser_dataReady", pdfData => {
fs.writeFile("./sometxt.txt", pdfParser.getRawTextContent());
pdfParser.loadPDF("./page1.pdf");
You can require it conditionally by testing if it is the server:
static async getInitialProps({isServer}){
var fs;
if(isServer){
fs=require('fs');
//and do what ever you want
}
}
and dot not forgot to tell webpack to do not send the module to the client side by changing package.json like so:
"browser": {
"fs": false
}
unless it can produce errors.
The thing that's probably biting you is that most of your code must work on both the client and the server. You can write server-only code by creating a getInitialProps() method and checking to see if it's passed in a opts.req - if so, you know the code is running server-side and you can hit the filesystem:
import React from 'react'
const doServerSideStuff = () => {
let fs = require('fs');
var PDFParser = require("pdf2json");
let pdfParser = new PDFParser(this,1);
pdfParser.on("pdfParser_dataError", errData =>
console.error(errData.parserError) );
pdfParser.on("pdfParser_dataReady", pdfData => {
fs.writeFile("./sometxt.txt", pdfParser.getRawTextContent());
pdfParser.loadPDF("./page1.pdf");
}
export default class extends React.Component {
static async getInitialProps ({ req }) {
if (req) {
doServerSideStuff();
}
return {};
}
render () {
return <div> Hello World </div>
}
}
This isn't really a complete example yet, you should really make doServerSideStuff() async (or return a promise) and then await it in getInitialProps, and eventually return props that represent the result of the parsing & saving. Also, handle fs.writeFile errors. But, hopefully it's enough to get you going in the right direction.
See the docs for some more info on this.
Or you could just use Express like you suggested. There is a good tutorial and example code that should help you get started if you decide to go that route.

How to check internet connection every http request in react native and display alert message?

I'm just trying to check internet connection when app launches and also check internet connectivity before calling HTTP Request.I have seen some example but it's confusing for me.Please guide me.
You can use the NetInfo API from react native.
Here is the example:
componentDidMount() {
NetInfo.isConnected.addEventListener(
'change',
this._handleConnectivityChange
);
NetInfo.isConnected.fetch().done(
(isConnected) => { this.setState({isConnected}); }
);
}
componentWillUnmount() {
NetInfo.isConnected.removeEventListener(
'change',
this._handleConnectivityChange
);
}
_handleConnectivityChange = (isConnected) => {
this.setState({
isConnected,
});
};
render() {
return (
<View style={styles.container}>
<Text>{this.state.isConnected ? 'Online' : 'Offline'}</Text>
</View>
);
}
}
Thereby the above code lets you know if you are having internet before making any api call in your app.
You can refer https://facebook.github.io/react-native/docs/netinfo.html for more.
Here is the example:
import { NetInfo,Alert } from 'react-native';
const netStatus = await NetInfo.fetch()
if (netStatus === 'none' || netStatus === 'NONE') {
Alert.alert("Internet not connected ")
return []
}
There probably is a better way to do this, but you could do a console.log() before the HTTP request and pass in parameters of the API, if you get a result of the title in your console, then you're connected to the internet, otherwise you're not.
You should hook this into your api calls before making them. In such case a higher order function would be useful.
import NetInfo from "#react-native-community/netinfo";
import api from "./MyApi"
//higher order function for api calls
const connectionWrapper = async (errorHandler, apiRequest) => () => {
NetInfo.fetch().then(state => {
return state.isConnected
? errorHandler(state)
: apiRequest()
})
}
//use connection wrapper to build your resource calls
const apiCall = connectionWrapper(
state => ...handleError,
api.resource({ myParams : "myParams"})
)
//now you can reuse api call which should return a promise or anything else that you want
var firstCall = apiCall()
var secondCall = apiCall()
var thirdCall = apiCall()