React w/SignalR - TypeError: WebSocketClient() not a constructor - node.js

new to React development.
I am building an API client for the BitTrex Exchange API, using their node.js wrapper: node.bittrex.api
With the objective of simply testing the websocket subscription for orderbook updates within the ReactJS framework, here are the steps I have taken:
-Used create-react-app to create the app.
-used npm to install the node.bittrex.api
-added the bittrex client object to the top of the default App.js component and configured options with proper API keys
-added a button (with handler, binded to the button according to React docs) to the default App.js main component,
-inside the handler function, initiated the websocket subscription according to the example code in the node.bittrex.api docs.
The app comes up, but when I press the button, I get an error saying that TypeError Websocketclient() is not a constructor, in the line inside the SignalR.js that creates the websocket connection:
Now I suspect that there is just something specific with the React framework that is screwing this up. Can anyone please help me understand the intricacies? Thanks. Here is my App.js:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
var bittrex = require('../node_modules/node.bittrex.api/node.bittrex.api.js');
bittrex.options({
'apikey' : process.env.REACT_APP_BTREX_API_KEY,
'apisecret' : process.env.REACT_APP_BTREX_SECRET_KEY,
'verbose' : true,
'cleartext' : false,
'baseUrl' : 'https://bittrex.com/api/v1.1'
});
class App extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
bittrex.websockets.subscribe(['BTC-ETH','BTC-ANS','BTC-GNT'], function(data) {
if (data.M === 'updateExchangeState') {
data.A.forEach(function(data_for) {
console.log('Market Update for '+ data_for.MarketName, data_for);
});
}
});
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<br/>
<button onClick={this.handleClick}>Start WS Sub</button>
</div>
);
}
}
export default App;

Related

What's wrong with my routing in my react application?

I have a React application that I just deployed to my server and now the routing isn't working as expected. I need some help figuring it out.
When running locally, this works:
<button className="welcome-buttons"
onClick={() => window.location.href = 'http://localhost:3000/services'}>
Read More <i className="fas fa-arrow-alt-circle-right"></i>
</button>
I would click on the button and it would route to http://localhost:3000/services. Then when I was ready to deploy, I changed this to http://www.assertivesolutions.ca/services, created a build and uploaded it to my server. I would go to my site (http://www.assertivesolutions.ca) and it would load fine, but when I clicked on the button, I get taken to a page that says Cannot GET /services.
I'm not sure why this is. Maybe I can't just replace localhost:3000 with www.assertivesolutions.ca in the code. But what is the right way to do it?
This is what I have in app.js
import React, { Component } from 'react';
import './App.scss';
import './Home.scss';
import Header from './Header/Header';
import Banner from './Banner/Banner';
import Welcome from './Welcome/Welcome';
import MainFocus from './MainFocus/MainFocus';
import WhatWeDo from './WhatWeDo/WhatWeDo';
import OurBlog from './OurBlog/OurBlog';
import OurClients from './OurClients/OurClients';
import ContactUs from './ContactUs/ContactUs';
import Footer from './Footer/Footer';
import smoothscroll from 'smoothscroll-polyfill';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Blog from './Blog/blog';
import OurServices from './OurServices/OurServices';
import SideMenu from './SideMenu/SideMenu';
class App extends Component {
render() {
smoothscroll.polyfill();
return (
<Router>
<Switch>
<Route path="/" exact>
<div className="app-master-container">
<SideMenu pageWrapId={'page-wrap'} outerContainerId={'outer-container'} />
<div className="header"><Header /></div>
<Banner />
<Welcome />
<MainFocus />
<WhatWeDo />
<OurBlog />
<OurClients />
<ContactUs />
<Footer />
</div>
</Route>
<Route path="/blog">
<Blog/>
</Route>
<Route path="/services">
<OurServices/>
</Route>
</Switch>
</Router>
);
}
}
export default App;
On the server, I'm running node and bouncy to handle the routing to each website I host, like this:
const bouncy = require('bouncy');
const express = require('express');
const path = require('path');
const { create, engine } = require('express-handlebars');
bouncy(function(req, bounce) {
const host = req.headers.host;
console.log(`host=${host}`);
if (host === 'shahspace.com' || host === 'www.shahspace.com') {
if (req.url.includes('/music%20mixes/')) bounce(8002);
else bounce(8000);
}
if (host === 'assertivesolutions.ca' || host === 'www.assertivesolutions.ca') bounce(8001);
if (host === 'fmshahdesign.com' || host === 'www.fmshahdesign.ca') bounce(8003);
}).listen(80);
const fmsApp = express();
fmsApp
.use(express.static(path.join(__dirname, 'fmshahdesign.com')))
.listen(8003);
const assertSolApp = express();
assertSolApp
.use(express.static(path.join(__dirname, 'assertivesolutions.ca')))
.listen(8001);
const musicMixApp = express();
musicMixApp.engine('.hbs', engine({
extname: 'hbs',
defaultLayout: false
}));
musicMixApp.set('view engine', 'hbs');
musicMixApp.set('views', path.join(__dirname, 'shahspace.com/music mixes/views'));
/****** more code for handling music mix app ********/
In other words, all requests come in on port 80 where the node router is listen, and then it checks the host to see which website is being requested. That's where bouncy comes in. It bounces the request to the appropriate port corresponding to the requested website. assertivesolutions.ca is on port 8001 so it bounces it there. Each site has an app created with express which handles the request on the appropriate port.
This works as long as I go to www.assertivesolutions.ca but as soon as I go to www.assertivesolutions.ca/services, it get the Cannot GET /services message. I would create a services folder in the assertivesolutions.ca folder (where the assertSolApp directs requests to) but the contents were created by the build (which I would think should be able to handle requests for /services) so I don't think I should mess with that.
Can anyone see the problem? Thanks.
If you're not sure about your url . Instead of Redirect to Another Webpage with vanilla javascript you can use react router (which you're already using and it seems version 5 ) .
Just add it to your component like this :
in functional components :
import { useHistory } from "react-router-dom";
..............
let history = useHistory();
<button className="welcome-buttons"
onClick={() => history.push("/services")}>
Read More <i className="fas fa-arrow-alt-circle-right"></i>
</button>
in class components :
You can get access to the history object’s properties via the withRouter which is a higher-order component. you can do something like this :
import { withRouter } from "react-router-dom";
class Example extends React.Component {
render() {
return (
<div>
.........
<button className="welcome-buttons"
onClick={() => this.props.history.push("/services")}>
Read More <i className="fas fa-arrow-alt-
circle-right"></i>
</button>
</div>
);
}
}
export default withRouter(Example);
this is a simple codesandbox showing how o implement withRouter
You need to write the .htaccess file in the server root directory.
Check this link

Unable to send api response data from express to react after refreshing the page

I'm learning react and node js with express framework and I'm working on a project where I need to retrieve API data from express to react.
I retrieved data from backend express js where I made a simple json value. My backend server.js code is given below.
server.js
const express = require('express')
const app = express()
const PORT = 3001;
app .get('/api/contents',(req,res)=>{
const contents=[
{
"id":0,
"heading":"Joshua Tree Overnight Adventure",
"content":"A sight in the blue sea..."
},
{
"id":1,
"heading":"Catch waves with an adventure guide",
"content":"Lorem.."
},
{
"id":2,
"heading":"Catch waves with an adventure guide",
"content":"Lorem epsum ..."
}
];
res.json(contents)
})
app.listen(PORT,()=>{
console.log("express server is running...")
})
In react app, I used axios to retrieve those values from backend and tried to pass the api values of content with id= 0 as props in "TheLatestArticles" component. I have updated proxy in package.json in react to connect backend. The below code is the mainhomepage component where it is enclosed with TheLatestArticles component with props value
MainHomePage.js
import axios from 'axios';
import {useState,useEffect} from 'react'
function MainHomePage(){
const [content,setContent]=useState([]);
useEffect(()=>{
const fetchPosts = async ()=>{
const res =await axios.get("/api/contents")
setContent(res.data)
console.log(res)
}
fetchPosts()
},[])
return (
<>
<TheLatestArticle content={content} />
</>
);
}
export default MainHomePage;
TheLatestArticle.js
import cardImage from "./../../Images/card.jpg"
import './TheLatestArticleCard.css';
const TheLatestArticleCard=(props)=>{
console.log(props)
return(
<>
<div className="card">
<div className="image">
<img src={cardImage} alt="cardimg"/>
</div>
<div className="content">
<p className="heading">{props.content.heading}</p>
<p className="body-content">{props.content.content}</p>
<div className="details">
<p className="details-info">Travel <span className="details-info-2">/ August 21 2017</span></p>
</div>
</div>
</div>
</>
)
}
export default TheLatestArticleCard;
When I run the application, It displayed all the api values in the screen given below.
I console.log the api values inside useEffect and it displayed all the api values perfectly.
But when I refresh the page, the api value became undefined and gave me this error
Can you please solve me this issue with the reason behind this error? Thanks a lot!
Try it like this
{(content && content.length > 0) && <TheLatestArticle content={content} />}
Since your API call is async there won't be any data in content initially. After a while, your API is called and data is fetched. Then you will have data. To prevent TheLatestArticle to blow up we add some conditions when to show that component. The error in the screenshot is when you try to use a property heading from content where content is empty.
Now with the condition, TheLatestArticle will not render until there is some data.
Update
You are using <TheLatestArticle content={content} /> and content is assumed to be an object. But as per your code, it's an array. If you are not already using content.map((c)=> <TheLatestArticle content={c} />) you should do that.

Unable to add an UI extension on Contentful. When i run nopm run start, I get a 404 error on ui_config

I am new to contentful. I am trying to develop an UI extension on Contentful using Contentful SDK.
I followed all the steps mentioned in this article.
This is the code I have in index.js.
import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { TextInput , Button } from '#contentful/forma-36-react-components';
import { init } from 'contentful-ui-extensions-sdk';
import '#contentful/forma-36-react-components/dist/styles.css';
import './index.css';
export class App extends React.Component {
static propTypes = {
sdk: PropTypes.object.isRequired
};
detachExternalChangeHandler = null;
constructor(props) {
super(props);
this.state = {
value: props.sdk.field.getValue() || ''
};
}
componentDidMount() {
this.props.sdk.window.startAutoResizer();
// Handler for external field value changes (e.g. when multiple authors are working on the same entry).
this.detachExternalChangeHandler = this.props.sdk.field.onValueChanged(this.onExternalChange);
}
componentWillUnmount() {
if (this.detachExternalChangeHandler) {
this.detachExternalChangeHandler();
}
}
onExternalChange = value => {
this.setState({ value });
};
onChange = e => {
const value = e.currentTarget.value;
this.setState({ value });
if (value) {
this.props.sdk.field.setValue(value);
} else {
this.props.sdk.field.removeValue();
}
};
onButtonClick = async () => {
console.log('hurray');
};
render() {
return (
<Button buttonType="primary" isFullWidth={false}
onClick={this.onButtonClick}>
Add Content from AEM DAM
</Button>
);
}
}
Ideally i am trying to create an UI extension to be used in contentful space. I downloaded the contentful SDK and i have put in a button. But I receive this error on the console and it doesn't work
Screenshot:
https://github.com/contentful/create-contentful-extension
Go to the content of this Content Type and enable mixed content at
your browser so that development version that is served from your
local machine could be rendered within https://app.contentful.com.
Better yet:
I'm not the biggest fan of disabling the mixed content setting in browsers. Can I use HTTPS in development mode?
Yes, you can serve your extension using HTTPS. Add --https to start command.
"start": "contentful-extension-scripts start --https",
It uses Parcel HTTPS under the hood , which generates a self-signed certificate, you might have to configure your browser to allow self-signed certificates for localhost.
I think that will fix the 404 error and get things working.
Please follow the readme carefully and post a separate question if you still have problems.

Fetching API from react sending me wrong URL

Learning React.js and Node.js and making a simple crud app with Express API on the back-end and React.js on the front end.
App.js of my React.js looks like this.
`import React, { Component } from 'react';
import './App.css';
import Rentals from './components/Rentals';
import Idpage from './components/Idpage';
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom';
class App extends Component {
render() {
return (
<div className="mainappdiv">
<Router>
<main>
<Route exact path="/" component={Home} />
<Route exact path="/rentals" component={Rentals} />
<Route path="/rentals/:propertyid" component={Idpage} />
</main>
</div>
</Router>
</div>
);
}}
export default App;
I am making an app that when if you go to /rentals, it will fetch the data and print stuff. This is currently working and all the data from my database is rendering.
Now I am trying to go to /rentals/1 or /rentals/2 then trying to print only listings of that id.
import React, { Component } from 'react';
class Idpage extends Component {
componentDidMount() {
fetch('api/listofrentals/2')
.then((response)=>{
console.log(response)
return response.json()
})
.then((singlerent)=>{
console.log(singlerent)
})
}
render() {
return (
<div>
<p>this is the id page solo</p>
<p>{this.props.match.params.propertyid}</p>
</div>
);
}}
export default Idpage;
When I do this, I get an error saying GET http://localhost:3000/rentals/api/listofrentals/2 404 (Not Found)
I am trying to fetch from the URL http://localhost:3000/api/listofrentals/2 and do not understand why the "rentals" part is in the url.
My React server is running on localhost:3000 and node.js is running on localhost:30001. And my React's package.json has this "proxy": "http://localhost:3001/"
Fetch by default will access a relative path to where you are using it. You can specify you want to bypass the relative path by starting your url with /.
fetch('/api/listofrentals/2')
In case if you want to change the base url for testing. You can turn off web security in Google and use.
In ubuntu command line it is
google-chrome --disable-web-security --user-data-dir

Checksum Invalid - SSR props to Client

I'm using the react engine react-engine on GitHub to create a node, express app with react for the views.
For the most part, my app is rendered on the server. However, on one page/express route I require the view to be rendered server-side and then for the React to be fully interactive on the client.
So far I've got the view rendering server-side and then being re-loaded/re-mounted by React on the client.
My problem is that I'm now getting the following error:
bundle.js:357 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) <section data-reactroot="" data-reactid
(server) <section cl
Here's what my code looks like:
class FormCreate extends React.Component {
render() {
return (
<ReactBlank title="Create new application form" messages={this.props.messages} authUser={this.props.authUser}>
<script dangerouslySetInnerHTML={{
__html: 'window.PROPS=' + JSON.stringify(this.props)
}} />
<div id="app-content">
<Main {...this.props}/>
</div>
</ReactBlank>
);
}
}
FormCreate.propTypes = {
messages: React.PropTypes.array,
authUser: React.PropTypes.object,
form: React.PropTypes.object
};
module.exports = FormCreate;
The above is initially rendered on the server and then the following re-mounts it on the client:
var React = require('react');
var ReactDOM = require('react-dom');
var Main = require('./app/views/shared/builder/Main.jsx');
document.addEventListener('DOMContentLoaded', function onLoad() {
const propScript = document.getElementById('react-engine-props');
const props = window.PROPS;
ReactDOM.render(
<Main {...props} />,
document.getElementById('app-content')
);
});
Can anyone see a problem here?

Resources