I have almost googled my fingers off trying to figure this out. It seems a lot of the existing info on connecting socket.io with React Native is outdated, or maybe I'm just interpreting things wrong?
I've managed to get the client-side connected (I'm getting the client console logs when I connect to my app). It seems to be the server-side that's giving me issues. Why is the data being emitted from the client not showing up as a log in my terminal? None of the related console.logs in my server.js are logging but the App.js console.logs are registering.
Edit: Here is my full App.js file:
import Expo from 'expo';
import React from 'react';
import { Dimensions, StyleSheet, Text, View } from 'react-native';
import store from './src/store';
import { Provider } from 'react-redux';
// window.navigator.useragent = 'react-native'; -> not necessary anymore?
const ROOT_URL = 'https://myherokudomain.herokuapp.com';
const io = require('socket.io-client/dist/socket.io');
const socket = io.connect(ROOT_URL);
socket.on('connect', () => {
console.log('Connected to server');
});
socket.on('example', (data) => {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
socket.on('disconnect', () => {
console.log('Disconnected from server');
});
export default class App extends React.Component {
render() {
// const MainNavigator = my react-navigation system
return (
<Provider store={store}>
<View style={styles.container}>
<MainNavigator />
</View>
</Provider>
);
}
}
Edit: Here is my full server.js file:
const config = require('./config/config');
const { mongoose } = require('./db/mongoose');
const express = require('express');
const cors = require('cors');
const app = express();
const port = process.env.PORT;
// ************ Include and use separate routes file
app.use(require('./routes/routes'));
// ************
//Cross-Origin resource sharing. cors library solves CORS problems.
app.use(cors());
//***********
/* Chat server code*/
// enabled heroku session affinity:
// see https://devcenter.heroku.com/articles/session-affinity
// to enable: heroku features:enable http-session-affinity
// to diable: heroku features:disable http-session-affinity
const socketIO = require('socket.io');
const http = require('http');
const server = http.createServer(app);
const io = socketIO(server, { origin: "*:*" });
//********** */
io.on('connection', (socket) => {
console.log('A client just joined', socket.id);
socket.emit('example', { hello: 'world' });
socket.on('my other event', (data) => {
console.log(data);
});
socket.on('disconnect', () => {
console.log('User was disconnected');
});
});
server.listen(port, (err) => {
console.log(`started on port ${port}`);
});
module.exports = { app };
I am getting the console logs on the client side just fine (for instance, the "connected to server" and "hello: world" stuff is showing up when I open my app on expo. But I am not getting the server-side console logs.
What am I doing wrong - how do I get socket.io fully working with a deployed React-Native app?
I would really appreciate any help at all! I've been stuck on this forever.
I'm assuming all the code works, just not the logging since that's all you're asking about. The problem is Node doesn't output to your browser's console.
If it's deployed on heroku then you should see everything being logged there, otherwise you can use libraries like https://github.com/node-inspector/node-inspector to output to your browser.
You're not getting the server-side console logs because 1.) They're only logging on the server, and 2.) You're not emitting them, if you do actually want to send the data back.
Related
I'm trying to successfully connect my backend Express app to my frontend React app but I'm having difficulty with the actual connection process and I think it's to do with the "proxy" pathway I'm using in my package.json file in my react app.
Express
const express = require('express')
const app = express()
let name = "Justin"
app.get('/', (req, res) => {
res.send(name)
})
app.listen(40000, () => {
console.log("Im Listening on port 40000")
})
React
import './App.css';
function GetData() {
fetch('/')
.then((response) => response.text())
.then(function (data) {
console.log(data)
}
)};
function App() {
return (
<div className="App">
<button onClick={GetData}>Get Data</button>
</div>
);
}
export default App;
I've made sure to add the proxy route to the express server within my package.json file
"proxy": "http://localhost:40000",
The only thing that happens when I click the button is a text representation of the react app html page source.
What I want to see is the name "justin" displayed in the console when I click the button.
Would love a quick solve
can i get help with something im stuck on for awhile
im establishing a socket .io connection in my frontend with react context,
but the connection is triggered as soon as my web load, i want it to connect only AFTER i login
im running a jwt auth on my socket connection and what happens is it fails to auth because i dont have a chance to login before it checks it
and then after i log in it wont establish connection untill i manually reload the page...
😦
client:
import React from 'react';
import io from 'socket.io-client'
import { SOCKET_IO_URL } from '../api/config';
const jwt = JSON.parse(localStorage.getItem('profile'))?.token
console.log(jwt)
export const socket = io.connect(SOCKET_IO_URL, {query: {token: jwt}});
export const SocketContext = React.createContext()
server:
io.on('connection', (socket => {
const token = socket.handshake.query.token;
try {
if (!token) throw new Error("TOKEN NOT FOUND")
jwt.verify(token,'secret')
} catch (error) {
console.log('VERIFICATION FAILED')
socket.disconnect()
}
console.log('socket conected', socket.id)
socket.on('request_fetch', () => {
socket.broadcast.emit('response_fetch')
})
}))
You can import the socket / use the socket only in areas where you are logged in.
And lazy import those components
const Dashboard = lazy(() => import('./pages/Dashboard'))
that way the token will always be available when loading those components
According to the docs in the client options, there is an option autoConnect
Client Options
Set this to false as it defaults to true then manually try to connect after you have logged in with socket.connect
I'm trying to listen to changes from Sails socket in the front-end using react.
Server listen to changes in a MongoDB Collection and blasts the changes:
// Setting up connection to MongoDB
const RTPEntryDB = sails.getDatastore("RTPEntrydb").manager;
// Switching to the appropriate collection in MongoDB
const profilesCollection = RTPEntryDB.collection("workloads");
// MongoDB Change Stream - Detect changes in DB's collection
const changeStream = profilesCollection.watch();
changeStream.on("change", function(change) {
console.log("new change", change);
sails.sockets.blast('newWorkloads', change);
})
This is working perfectly fine.
But on the front-end, I couldn't listen
import React, { useRef, useReducer, useEffect } from 'react';
import PropTypes from 'prop-types';
import socketIOClient from 'socket.io-client';
import sailsIOClient from 'sails.io.js';
const FetchWorkloads = (props) => {
// Instantiate the socket client (`io`)
const io = sailsIOClient(socketIOClient);
io.sails.url = 'http://localhost:1337/';
io.socket.on('connect', function onConnect(){
console.log('This socket is now connected to the Sails server!');
});
io.socket.on('newWorkloads', (msg) => {
console.log('workloads changed', msg);
});
return (
<>
{/* My Component */}
</>
);
}
FetchWorkloads.propTypes = {
api: PropTypes.object.isRequired
};
export default FetchWorkloads;
I'm getting the error GET http://localhost:1337/__getcookie net::ERR_ABORTED 404 (Not Found). How do I resolve this?
Thanks
I resolved this by defining a custom __getcookie in routes.js as follows:
'GET /__getcookie': (req, res) => {
return res.send('_sailsIoJSConnect();');
},
There was also another issue with the compatibility between sails.io.js and socket.io-client. I was using the latest version of socket.io-client (v4.4) but sails was only compatible with v2.x.
I've been told that Axios is how you get React to talk to an api (external or internal). So far, I have specifically only received 404 errors whenever I try to implement Axios calls.
Here is the axios call in client/src/App.js:
import React, {Component} from 'react';
import './App.css';
import API from "./utils/API";
class App extends Component {
state = {
recipes: []
}
componentDidMount = () => {
API.getRecipes("milk") /* This is supposed to call the getRecipes
function in API.js with "milk" as the only
parameter (ie - Search the api for "milk"
related recipes). */
.then(res => this.setState({recipes: res.data}))
.catch(err => console.log(err));
}
render(){
return (
<div>
{
this.state.recipes.map(recipe => {
return(
<p>
{recipe.title} // All recipe names are then set to a p tag
</p>
)
})
}
</div>
);
}
}
export default App;
Now, this calls API.js in the "utils" folder:
import axios from "axios";
// Function that takes the parameter and is supposed to send it to the
/api/recipes route
export default {
getRecipes: function(query) {
return axios.get("/api/recipes", { params: { q: query } });
}
};
The relevant api route (/api/recipes) is located in a folder named "routes" outside of the "src" folder. This file is the only item inside the folder.
const axios = require("axios");
const router = require("express").Router();
/* As you can see, this sends the request to "recipepuppy.com" with the
relevant query ("milk").*/
router.get("/recipes", (req, res) => {
axios.get("http://www.recipepuppy.com/api/", {params: req.query})
.then(({data: {results}}) => {res.json(results)})
.catch(err => res.status(422).json(err));
});
module.exports = router;
Going even further out, here is the server.js file (outside of the "client" folder) that determines the routes:
const express = require("express");
const path = require("path");
const PORT = process.env.PORT || 3001;
const app = express();
const apiRoutes = require("./routes/apiRoutes"); // *********
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
app.use("/api", apiRoutes); // *********
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
app.listen(PORT, function() {
console.log(`API server now listening on port ${PORT}.`);
});
As far as I can tell, everything is set up perfectly. However, every single time I boot up the server, the browser console error pops up and says:
GET http://localhost:3000/api/recipes?q=milk 404 (Not Found)
Even though server.js directly ties to the apiRoutes folder, and the axios call within API.js calls the exact same route that would result from going to the /api route, then the /recipes route within /api (resulting in /api/recipes).
If anybody here can tell me what is going on and how to fix it, I would appreciate it.
I didn't have "proxy" set in my dependencies (package.json) in the client folder.
Once I set "proxy" to "localhost:3001" (the same as my initial server.js port value) and restarted the server, it worked immediately.
Proxy error: Could not proxy request /api/games from localhost:3000 to http://localhost:8080/ (ECONNREFUSED).
code in action.js (Redux)
export function fetchGames(){
return dispatch =>{
fetch('/api/games')
}
}
import express from 'express';
import mongodb from 'mongodb';
const app = express();
const dbUrl = 'mongodb://onkar localhost:27017/crudwithredux';
mongodb.MongoClient.connect(dbUrl, function(err, db) {
app.get('/api/games', (req, res) => {
db.collection('games').find({}).toArray((err, games) => {
res.json({ games });
});
});
app.listen(8080, () => console.log('Server is running on localhost:8080'));
});
** Hi i m onkar, I am new in react js. i getting error in server page. I have mongo db database so i m retrieve the data from mongo db. and show in Json format in react js using redux.**