Getting API to work in JSX - javascript

My code below is from my container, but if I pull out just the Twilio API and place it in a seperate .js file, it works when I execute it in on the CLI using node, but not in my JSX file. I need it to execute on the click of a button, within my getTime method, but each time I attempt to build my app with webpack after incorporating the twilio module, I receive errors stating "cannot find net", "cannot find tls" and "cannot find fs". What can I do to get around this, and incorporate the Twilio api in my code.
import React, { Component, PropTypes } from 'react';
var firebase = require('firebase');
var hash = require('object-hash');
var AccountSid = "**********";
var AuthToken = "*************";
var twilio = require('twilio');
var client = new twilio.RestClient(AccountSid, AuthToken);
export default class App extends Component {
componentWillMount(){
//Send an SMS text message
client.messages.create({
to: "+15558675309",
from: '+**',
body: "This is the ship that made the Kessel Run in fourteen parsecs?",
mediaUrl: "https://c1.staticflickr.com/3/2899/14341091933_1e92e62d12_b.jpg",
});
}
getTime(){
var localTime = new Date();
var bob = {first: 'Bob', last: 'Samuels', time: localTime };
var convert = localTime.toLocaleString();
alert(hash(bob));
alert(convert);
}
render(){
return (
<div>
<h1>YES !</h1>
<button onClick ={ this.getTime }>Clock In</button>
<button onClick ={ this.getTime }>Clock Out</button>
</div>
);
}

From #azium:
you're getting those errors because you're trying to load a server
side library on the client. you might need a server side proxy (node
server) that your client side app calls
just expose a different endpoint like /api/createMessage that handles
twilio logic, and hit that endpoint from react

Related

How do I store my Spotify access_token local so I can access it in different Javascript files

Hi Im relatively new to coding with Javascript, and Im trying to work out how I can access Spotify API's access_token within different javascript files. Im running two local server, one React and the other in node. The React server has a button that allows the user to login with Spotify's Oauth in the node server and then the access token and refresh token are redirect successfully back to the react server. The OAuth works quite well as I got it from the Spotify API guide they provide. The way I set up these files is that in my main project I have a auther-server older which includes the Spotify OAuth files and a client folder which is where i create my React app in. Here is where i got the OAuth files( https://github.com/spotify/web-api-auth-examples ). The only things changed in these files was in the app.js found in authorization_code folder where I entered my client and secret id with the correct redirect url, and I also did:
res.redirect('http://localhost:3000/#' +
querystring.stringify({
access_token: access_token,
refresh_token: refresh_token
}));
} else {
res.redirect('/#' +
querystring.stringify({
error: 'invalid_token'
}));
where I made the redirect link go to http://localhost:3000/# with the tokens which is my React app is. From there I go to my React directory and in the App.js file I follow a guide i found on youtube which helps me get what the user is now playing ( https://www.youtube.com/watch?v=prayNyuN3w0&t=1496s). Here is the code:
import React, { Component, useEffect } from "react";
import "./App.css";
import Spotify from 'spotify-web-api-js';
const spotifyWebApi = new Spotify();
class App extends Component {
constructor() {
super();
const params = this.getHashParams();
this.state ={
loggedIn: params.access_token ? true : false,
nowPlaying: {
name: 'Not Checked',
image: '',
}
}
if (params.access_token){
spotifyWebApi.setAccessToken(params.access_token)
}
}
getHashParams() {
var hashParams = {};
var e,
r = /([^&;=]+)=?([^&;]*)/g,
q = window.location.hash.substring(1);
while ((e = r.exec(q))) {
hashParams[e[1]] = decodeURIComponent(e[2]);
}
return hashParams;
}
getNowPlaying(){
spotifyWebApi.getMyCurrentPlaybackState()
.then((response) => {
this.setState({
nowPlaying:{
name: response.item.name,
image: response.item.album.images[0].url
}
})
})
}
render() {
return (
<div className="App">
<a href="http://localhost:8888">
<button>Login With Spotify</button>
</a>
<div>Now Playing: {this.state.nowPlaying.name}</div>
<div>
<img src={ this.state.nowPlaying.image } style={{width: 100}}/>
</div>
<button onClick={() => this.getNowPlaying()}>Check Now Playing</button>
<br></br>
</div>
);
}
}
export default App;
This all works nicely, but Im trying to now access the user's data( playlists) so I can later make new recommendations using Naive Bayes and KNN classifiers, but Ill tackled that after I get over this bit first. Ive looked up ways of storing the tokens and found localStorage.set(token....) to store it in the browser but I havent had success with it as I am confused on where to set this in my code. I think its also worth to note im using the spotify web api js libary, https://github.com/jmperez/spotify-web-api-js . Im guessing that i would make a similar function in the class App like the getNowPlaying() to get the playlists, but I keep getting lost. This is my first question on here, and I probably didnt do a good job of explaining my issue here, but i hope i can find some help on here. Thanks and let me know if I need to provide any more information. :)
You are probably on a good lead to do what you want with localStorage.set.
It is globally accessible. You can to the localStorage.set from wherever you retrieve the token to store it. Then you will be able to do the localStorage.get from wherever you are in your app.
Using the localStorage is a good idea because it will help you keep this token between page refresh. You might want to remove it from localStorage at some point though for security purpose if someone might have access to the machine you use.
Another way if you do not want to use the localStorage is setting it on a separate JavaScript file that you would import wherever you might want to use it.
You can even look for store principles if you want to make that data centralization a step further.

Moving a file from a React.JS frontend to a C++ backend

So I have a function written in C++, that works on a file. I can convert it to a script and the script to take a parameter of the file location for example and work on it, that is not a problem.
My frontend is done with React, it is still not connected to the backend. I have a button that is "Upload File" the user clicks, and I need to have this file on my backend to run the C++ code on it.
Theoretically, the way I thought of (Not sure if it works):
User chooses the file to upload
From the frontend, we upload it to a cloud storage such as Google Drive for example
Then, from the Frontend I send an HTTP request using a REST API, with parameter as the file direct download link.
Then the REST API runs a Python function that executes the following shell commands:
wget (link that we got from the HTTP request through REST API
And after that the python script runs the C++ function on the file, and returns the output through the HTTP request.
Does that make sense?
Is there an easier or better way?
Thanks
Problem
Have the user load a file -> have the C++ function run on that file -> return output to the user.
Possible Solution with REST-API
As you stated in your question you could upload to google drive and then wget the file, however its a bit too complex for nothing. What you could do instead is skip the uploading to the Google drive and directly send the file through formdata.
Here is a working example in React taken from here:
import React from 'react'
import axios, { post } from 'axios';
class SimpleReactFileUpload extends React.Component {
constructor(props) {
super(props);
this.state ={
file:null
}
this.onFormSubmit = this.onFormSubmit.bind(this)
this.onChange = this.onChange.bind(this)
this.fileUpload = this.fileUpload.bind(this)
}
onFormSubmit(e){
e.preventDefault() // Stop form submit
this.fileUpload(this.state.file).then((response)=>{
console.log(response.data);
})
}
onChange(e) {
this.setState({file:e.target.files[0]})
}
fileUpload(file){
const url = 'http://example.com/file-upload';
const formData = new FormData();
formData.append('file',file)
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
return post(url, formData,config)
}
render() {
return (
<form onSubmit={this.onFormSubmit}>
<h1>File Upload</h1>
<input type="file" onChange={this.onChange} />
<button type="submit">Upload</button>
</form>
)
}
}
Possible Other Solution with AWS Lambda
For your specific use case I would not recommend having a full-blown REST-API, you could simply use a event-driven lambda function like AWS Lambda. This way you only need to upload to Google Drive or S3 bucket and then the Lambda will run and generate an output which can be returned to the user.

Can't send a message to Node.js websocket server from React client

I have following code as a server:
var http = require('http'),
cors = require('cors'),
connect = require('connect'),
WebSocketServer = require('ws');
var DataController = function() {
this.PORT = 8090;
this.startWS();
this.startServer();
}
DataController.prototype = {
// code to start server...
getMessage: function(_message) {
var that = this,
message = JSON.parse(_message),
msgName = message.name;
console.log('new message ' + msgName);
switch(msgName){
case 'start':
// here is some code to perform actions
}
As you can see here I have getMessage function that fires some events and to invoke it I need to send a message start. That's easy enough, right? Surpisingly for me, it's not.
That's how I try to perform this .send() method in my React component (my React app is running on different port of course):
import React, { Component } from 'react';
class App extends Component {
componentDidMount() {
const socket = new WebSocket('ws://localhost:8090');
socket.onopen = function() {
socket.send(JSON.stringify({message: "start"}));
}
}
render() {
return (
<div className="container">App</div>
)
}
}
export default App;
What I try to accomplish here - I need to send just one word - start to actually start receieving data from server but I can't and do not understand why. See, there's a console.log() statement in my server code that logs a message start when it's sent. So it actually should log start but it logs undefined instead.
What I tried so far:
1. Send just start
2. Define an object like this:
const data = {
message: "start"
}
And then pass data to .send() function
3. Define just a variable like this: const data = "start"
And nothing above works!Everything returns undefined on server side. I'm just getting started with websockets and can't find a way to get it working. I refered mostly to Mozilla and it didn't work too. So what actually am I doing wrong in this case? Thanks in advance, I appreciate any help!
It appears to me that the object you are sending over in your .send() does not contain a name key, so when you then define msgName as message.name it evaluates to undefined as that key does not exist in the object.
You can change this easily by changing the object you send over so that the key "start" is tied to would be called name.

Error when using React.js and the Twilio API

I'm investigating creating a small Twilio app for a project using React.js. I'm fairly good at React and JavaScript (but not an expert), but I'm having a bit of trouble.
Initially, I am trying to load all the messages on the account to the webpage. Here is the code I have:
import React from 'react'
import {connect} from 'react-redux'
var accountSid = '####';
var authToken = "####";
var client = require('twilio')(accountSid, authToken);
var msgList = []
const messages = () => {
client.messages.list(function(err, data) {
data.messages.forEach(function(message) {
msgList.push(message)
});
})
return msgList
}
class LandingPage extends React.Component {
render() {
return (
<h1>Hello!</h1>
)
}
}
export default connect(select)(LandingPage)
(of course, there are more files, but this is my current working file where I am having the issues).
First of all, when I load this up in my browser, I get an error in the console:
Uncaught TypeError: querystring.unescape is not a function
This apparently relates to the client.messages.list(function(err, data) { line.
Also, how would I go about rendering each message.body? I guess I would have to use a for loop but I'm not sure where that would go here.
The library you are trying to use was written for Node.js, and I assume you're trying to use it in the browser or in React Native? A couple bits:
You shouldn't use the Twilio API from a client side application with your account SID and auth token. These credentials are the "keys to the kingdom" for your Twilio account, and can be compromised if you put them in any client-side app.
The module you are trying to use was written for Node.js, and may not work out of the box in the browser. I haven't tested it, but it might work with Browserify if you were to package your front-end code that way.
For the use case you're trying to implement, I would fetch the messages on your server, and send them to the client via Ajax rather than hitting the API directly from the client.

How to Handle Post Request in Isomorphic React + React Router Application

I want to build Isomorphic react + react-router application and after a few days googling, now I can achieve isomorphic application that only handles GET request.
Here's what I've done so far:
Server use react-router to handle all request
react-router will call fetchData functions that resides in each React View that matches the route.
Set the data fetched before into props of the React View and render it into string
Inject the string and data fetched before as global variable window.__STATE__ into HTML and deliver the HTML to the client
We have successfully render React App from the server
When the client finished loading our React App javascript, it will try to render. But we pass the state from window.__STATE__ as the props of our React App, and React will not re-render because the state is the same
The problem is it will not work with POST/PUT/DELETE/WHATEVER request. When handling GET request, react-router have information about params and query. For example if we have a route: /user/:uid and client request this url: /user/1?foo=bar, then params would be: {uid: 1} and query would be {foo: 'bar'}
react-router then can pass it down to fetchData function so it will know to fetch user with uid of 1 and do whatever with foo query.
While in POST request, react-router doesn't know about the POST parameters. On Server, of course we could pass the POST parameters to fetchData function, but what about the Client? It doesn't know what the POST parameters are.
Is there a way that the server could tell the Client about the POST parameters? Below is an example of my Login View. I want when user submit the form, the server will render error message on error, or redirect it to dashboard on success.
fetchData.js
import whenKeys from 'when/keys';
export default (authToken, routerState) => {
var promises = routerState.routes.filter((match) => {
return match.handler.fetchData;
}).reduce((promises, match) => {
promises[match.name] = match.handler.fetchData(authToken, routerState.params, routerState.query);
return promises;
}, {});
return whenKeys.all(promises);
}
server.js
...
app.use((req, res) => {
const router = Router.create({
routes,
location: req.originalUrl,
onError: next,
onAbort: (abortReason) => {
next(abortReason);
}
});
router.run((Handler, state) => {
fetchData(authToken, state).then((data) => {
// render matched react View and generate the HTML
// ...
})
});
});
...
login.jsx
import React from 'react';
import DocumentTitle from 'react-document-title';
import api from './api';
export default class Login extends React.Component {
constructor(props) {
super(props);
// how to fill this state with POST parameters on error?
// how to redirect on success?
// and remember that this file will be called both from server and client
this.state = {
error: '',
username: '',
password: ''
};
}
// I saw some people use this function, but it'll only work if
// the form's method is GET
static willTransitionTo(transition, params, query) {
// if only we could read POST parameters here
// we could do something like this
transition.wait(
api.post('/doLogin', postParams).then((data) => {
transition.redirect(`/dashboard`);
});
);
}
render() {
return (
<DocumentTitle title="Login">
<div className="alert alert-danger">{this.state.error}</div>
<form method="post">
<input type="text" name="username" value={this.state.username} onChange={this._onFieldChange('username')} placeholder="Username" /><br />
<input type="password" name="password" value={this.state.password} onChange={this._onFieldChange('password')} placeholder="Password" /><br />
<button type="submit">Login</button>
</form>
</DocumentTitle>
);
}
_onFieldChange(name) {
var self = this;
return (e) => {
e.preventDefault();
var nextState = {};
nextState[name] = e.target.value;
self.setState(nextState);
}
}
}
Getting "POST" data on the client
On the client side, you get POST data by extracting values from your form inputs in a way which corresponds to what you would have received on the server had the form been submitted normally.
Using POST data
So now you have your POST data, but you still have the problem that there's no way to feed the POST data into your transition hooks in React Router 0.13.x and earlier. I created a pull request for this feature which has now been closed because it was included as part of the rewrite for the upcoming v1.0 release.
The gist of it is that locations now have a state object for squireling away any extra data you need about the current request/transition (the two are analagous) being handled:
On the server, you're dealing with one request at a time, so you create a static Location with data from req.body
On the client you pass the state object (containing extracted form data) to transitionTo().
Now your transition hook is capable of receiving the same form data in both environments. If things go well, great! If things don't go well, you need a way to pass errors and re-render the form again. New state object to the rescue again! Use transition.redirect() and pass both input data and errors and you now have everything you need to render on both sides.
I'm not going into more specific detail right now because v1.0 is still in beta and v0.13.x doesn't have the necessary API to do this anyway, but I have a repository which uses the pull request above to implement this workflow with 0.13.x which you could look at in the meantime:
isomorphic-lab - the README gives an overview of how things fit together.
Here are some rough flow diagrams of the process, too:
Server POST with errors and redisplay
Client POST with errors and redisplay
I've also created a few reusable modules related to this scenario:
get-form-data gets data from a form's inputs in the format it would have been POSTed in.
react-auto-form provides <AutoForm>, which you can use instead of <form> to receive all the data from a form's inputs as an argument to its onSubmit handler
react-router-form, which is to <form> what React Router's <Link> is to <a> - it handles triggering a transition to the given action, passing method and body (form data) state - this will be updated for v1.0 soon.

Categories