Related
I'm struggling to debug a problem and I'd appreciate any help the community might be able to offer. I'm building my first React app and have built a working Login feature, but after every successful login the user is forced to hard refresh his/her browser in order see the app in a "logged in" state. There is no error logged to the browser console, but our DevTools monitor shows the following error:
"TypeError: Cannot read property 'setState' of undefined"
What's funny is that the login authentication first succeeds, and then immediately seems to try again and fails. After clicking "login," the user must hard refresh the web page in order to make it appear that the login has worked.
I'm stumped. Can anyone see anything wrong with my code? Thank you very much in advance for taking a look!
Here's our LoginPage jsx file that contains the actual login web form:
import React from 'react';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
export default class LoginPage extends React.Component {
constructor(props) {
super(props);
//bound functions
this.compileFormData = this.compileFormData.bind(this);
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
//component state
this.state = {
email: '',
password: '',
};
}
//update state as email value changes
handleEmailChange(e) {
this.setState({ email: e.target.value });
}
//update state as password value changes
handlePasswordChange(e) {
this.setState({ password: e.target.value });
}
compileFormData() {
const { loginFunction } = this.props;
const formData = this.state;
loginFunction(formData);
}
render() {
return (
<div className="row justify-content-center">
<div className="col-10 col-sm-7 col-md-5 col-lg-4">
<Form>
<FormGroup>
<Label for="exampleEmail">Email</Label>
<Input
type="email"
name="email"
id="userEmail"
placeholder="test#mccre.com"
value={this.state.email}
onChange={this.handleEmailChange}
/>
</FormGroup>
<FormGroup>
<Label for="examplePassword">Password</Label>
<Input
type="password"
name="password"
id="userPassword"
placeholder="password"
value={this.state.password}
onChange={this.handlePasswordChange}
/>
</FormGroup>
<Button onClick={this.compileFormData}>Log In</Button>
</Form>
</div>
</div>
);
}
}
Here's our login page Container that renders the login page:
import React, { Component } from 'react';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { logUserIn } from '../../actions/authentication';
import LoginPage from './LoginPage';
export class LoginPageContainer extends React.Component {
constructor(props) {
super(props);
//bound functions
this.logUserInFunction = this.logUserInFunction.bind(this);
}
logUserInFunction(userData) {
const { dispatch } = this.props;
dispatch(logUserIn(userData));
}
render() {
const { authentication } = this.props;
if (authentication.isLoggedIn) {
return (
<Redirect to="/" />
);
}
return (
<div>
<LoginPage loginFunction={this.logUserInFunction} />
</div>
);
}
}
function mapStateToProps(state) {
return {
authentication: state.authentication,
};
}
export default connect(mapStateToProps)(LoginPageContainer);
Here's our API endpoint in which we actually make the database query:
const express = require('express');
const mongoose = require('mongoose');
const passport = require('passport');
const User = require('../../models/user.js');
const router = express.Router();
//configure mongoose promises
mongoose.Promise = global.Promise;
//POST to /register
router.post('/register', (req, res) => {
//Create a user object to save, using values from incoming JSON
const newUser = new User({
username: req.body.username,
firstName: req.body.firstName,
lastname: req.body.lastName,
email: req.body.email,
});
//Save, via passport's "register" method, the user
User.register(newUser, req.body.password, (err, user) => {
//If there's a problem, send back a JSON object with the error
if (err) {
return res.send(JSON.stringify({ error: err }));
}
// Otherwise, for now, send back a JSON object with the new user's info
return res.send(JSON.stringify(user));
});
});
//POST to /login
router.post('/login', async (req, res) => {
//look up user by their email
const query = User.findOne({ email: req.body.email });
const foundUser = await query.exec();
//If they exist, they'll have a username, so add that to our body
if (foundUser) {
req.body.username = foundUser.username;
}
passport.authenticate('local') (req, res, () => {
//If logged in, we should have use info to send back
if (req.user) {
return res.send(JSON.stringify(req.user));
}
//Otherwise return an error
return res.send(JSON.stringify({ error: 'There was an error logging in' }));
});
});
//GET to /checksession
router.get('/checksession', (req, res) => {
if (req.user) {
return res.send(JSON.stringify(req.user));
}
return res.send(JSON.stringify({}));
});
//GET to /logout
router.get('/logout', (req, res) => {
req.logout();
return res.send(JSON.stringify(req.user));
});
module.exports = router;
Here's the action file in which we define the logUserIn() function:
import { decrementProgress, incrementProgress } from './progress';
import 'whatwg-fetch';
//Action Creators
export const loginAttempt = () => ({ type: 'AUTHENTICATION_LOGIN_ATTEMPT' });
export const loginFailure = error => ({ type: 'AUTHENTICATION_LOGIN_FAILURE', error });
export const loginSuccess = json => ({ type: 'AUTHENTICATION_LOGIN_SUCCESS', json });
export const logoutFailure = error => ({ type: 'AUTHENTICATION_LOGOUT_FAILURE', error });
export const logoutSuccess = () => ({ type: 'AUTHENTICATION_LOGOUT_SUCCESS' });
export const sessionCheckFailure = () => ({ type: 'AUTHENTICATION_SESSION_CHECK_FAILURE'});
export const sessionCheckSuccess = json => ({ type: 'AUTHENTICATION_SESSION_CHECK_SUCCESS', json });
//Check User Session
export function checkSession() {
return async (dispatch) => {
//contact the API
await fetch(
//where to contact
'/api/authentication/checksession',
//what to send
{
method: 'GET',
credentials: 'same-origin',
},
)
.then((response) => {
if (response.status === 200) {
return response.json();
}
return null;
})
.then((json) => {
if (json.username) {
return dispatch(sessionCheckSuccess(json));
}
return dispatch(sessionCheckFailure());
})
.catch((error) => dispatch(sessionCheckFailure(error)));
};
}
//Log user in
export function logUserIn(userData) {
return async (dispatch) => {
//turn on spinner
dispatch(incrementProgress());
//register that a login attempt is being made
dispatch(loginAttempt());
//contact login API
await fetch(
//where to contact
'http://localhost:3000/api/authentication/login',
//what to send
{
method: 'POST',
body: JSON.stringify(userData),
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
},
).then((response) => {
if (response.status === 200) {
return response.json();
}
return null;
})
.then((json) => {
if (json) {
dispatch(loginSuccess(json));
this.setState({ redirect: true });
} else {
dispatch(loginFailure(new Error('Authentication Failed')));
}
}).catch((error) => {
dispatch(loginFailure(new Error(error)));
});
//turn off spinner
dispatch(decrementProgress());
};
}
//Log user out
export function logUserOut() {
return async (dispatch) => {
//turn on spinner
dispatch(incrementProgress());
//contact the API
await fetch(
//where to contact
'/api/authentication/logout',
//what to send
{
method: 'GET',
credentials: 'same-origin',
},
)
.then((response) => {
if (response.status === 200) {
dispatch(logoutSuccess());
} else {
dispatch(logoutFailure(`Error: ${response.status}`));
}
})
.catch((error) => {
dispatch(logoutFailure(error));
});
//turn off spinner
return dispatch(decrementProgress());;
};
}
Finally, here's the reducer file that is supposed to update the application's state depending on authentication success / failure:
const initialState = {
firstName: '',
id: '',
isLoggedIn: false,
isLoggingIn: false,
lastName: '',
username: '',
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case 'AUTHENTICATION_LOGIN_ATTEMPT': {
const newState = Object.assign({}, state);
newState.isLoggingIn = true;
return newState;
}
case 'AUTHENTICATION_LOGIN_FAILURE':
case 'AUTHENTICATION_SESSION_CHECK_FAILURE':
case 'AUTHENTICATION_LOGOUT_SUCCESS': {
const newState = Object.assign({}, initialState);
return newState;
}
case 'AUTHENTICATION_LOGIN_SUCCESS':
case 'AUTHENTICATION_SESSION_CHECK_SUCCESS': {
const newState = Object.assign({}, state);
newState.firstName = action.json.firstName;
newState.id = action.json._id;
newState.isLoggedIn = true;
newState.isLoggingIn = false;
newState.lastName = action.json.lastName;
newState.username = action.json.username;
return newState;
}
case 'AUTHENTICATION_LOGOUT_FAILURE': {
//todo: hanle error
return state;
}
default: {
return state;
}
}
}
Found the solution: "the this.setState({ redirect: true });" line needed to be removed from the action file.
I've been going crazy for a couple of days with an unresolved issue. Please help.
Working with a CSV database here. Creating own API. Small React App Fullstack MERN.
I'm trying to get to show all the employeees from my database.
I wrote the backend with express and have all the data now showing in json format on localhost:5000/employees
Also created a context on the front to deal with that data and reducer file for the functions.
Problem I have is I'm not beeing able to use the data on the ContextProvider file. ('EmployeesState')
Promise of my async function keeps giving me an undefined response. Tried both with fetch and axios but is not working.
Some of the code is from a previous project i did and it worked there so i 'm going crazy here. I can't seem to solve it. Please help.
BACKEND
db.js
const parse = require("csv-parse");
const fs = require("fs");
const employeesData = [];
const connectDB = () => {
fs.createReadStream(__dirname + "/employees1.txt")
.pipe(
parse({
delimiter: ",",
columns: true,
})
)
.on("data", (dataRow) => {
employeesData.push(dataRow);
})
.on("end", () => {
console.log(employeesData);
});
};
connectDB();
// console.log(connectDB());
module.exports = connectDB;
module.exports = employeesData;
server.js
var createError = require("http-errors");
var express = require("express");
const bodyParser = require("body-parser");
var cookieParser = require("cookie-parser");
const logger = require("morgan");
const cors = require("cors");
const connectDB = require("./config/db");
const employeesData = require("./config/db");
var path = require("path");
var app = express();
// const config = require("config");
//Connect DB
// connectDB();
let dataBase = employeesData;
console.log(employeesData);
app.use(cors());
// app.use(bodyParser.json()); //here
// Initial Middleware
//By doing this we can accepta data. Using the req.body
app.use(express.json({ extended: false }));
///Define Routes
app.use("/", require("./routes/index"));
app.use("/employees", require("./routes/employees"));
//Serve React in production
if (process.env.NODE_ENV === "production") {
//Set static folder (build folder)
app.use(express.static("client/build"));
app.get("*", (req, res) =>
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"))
);
}
// app.engine("html", require("ejs").renderFile);
app.set("view engine", "html");
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));
employees.js
const express = require("express");
const router = express.Router();
const config = require("config");
const { check, validationResult } = require("express-validator");
const Employee = require("../models/EmployeeModel");
const employeesData = require("../config/db");
// router.get("/", function (req, res) {
// res.send({ employeesData });
// });
//#route GET api/employees
//#desc Get all users Employees
//#access Private
router.get("/", async (req, res) => {
try {
const employees = await employeesData;
res.json({ employees });
} catch (err) {
console.error(err.message);
res.status(500).send("Server error");
}
});
//#route POST api/employees
//#desc Add new Employee
//#access Private
router.post(
"/",
[
check("name", "Name is required").not().isEmpty(),
check("surname", "Surname is required").not().isEmpty(),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { name, surname, adress, phone, email, birthdate } = req.body;
try {
const newEmployee = new Employee({
name,
surname,
adress,
phone,
email,
birthdate,
});
const employee = await newEmployee.save();
res.json(employee);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
}
);
//#route DELETE api/employee
//#desc Delete Employee
router.delete("/:id", async (req, res) => {
try {
let employee = await Employee.findById(req.params.id);
if (!employee) return res.status(404).json({ msg: "Employee not found" });
await Employee.findByIdAndRemove(req.params.id);
res.json({ msg: `Employee removed` });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
module.exports = router;
FRONTEND
EmployeesState.js
import React, { useReducer, useState } from "react";
import axios from "axios";
import { v4 as uuid } from "uuid";
import EmployeesContext from "./employeesContext";
import employeesReducer from "./employeesReducer";
import {
ADD_EMPLOYEE,
DELETE_EMPLOYEE,
SET_CURRENT,
CLEAR_CURRENT,
UPDATE_EMPLOYEE,
FILTER_EMPLOYEES,
EMPLOYEE_ERROR,
CLEAR_FILTER,
GET_EMPLOYEES,
CLEAR_EMPLOYEES,
} from "../types";
const EmployeesState = (props) => {
const initialState = {
employees: [],
current: null,
filtered: null,
error: null,
loading: false,
};
const [state, dispatch] = useReducer(employeesReducer, initialState);
const [employees, setEmployees] = useState(initialState);
//Get Employees
// // gives me promise{<prending>} on console
const getEmployees = async () => {
try {
const res = axios.get("http://localhost:5000/employees");
dispatch({ type: GET_EMPLOYEES, payload: res });
} catch (err) {
dispatch({
type: EMPLOYEE_ERROR,
});
}
};
//trying with fetch. throwing me undefined on console
const callAPI = () => {
fetch("http://localhost:5000/employees")
.then((res) => res.json())
.then((res) =>
setEmployees({
...initialState,
loading: false,
employees: res,
})
);
};
//Add Employee
const addEmployee = async (employee) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
const res = await axios.post("/employees", employee, config);
dispatch({ type: ADD_EMPLOYEE, payload: res.data });
} catch (err) {
dispatch({
type: EMPLOYEE_ERROR,
payload: err.response.data.msg,
});
}
};
//Delete Employee
const deleteEmployee = async (id) => {
try {
await axios.delete(`/employees/${id}`);
dispatch({ type: DELETE_EMPLOYEE, payload: id });
} catch (err) {
dispatch({
type: EMPLOYEE_ERROR,
payload: err.response.msg,
});
}
};
//Update Employee
const updateEmployee = async (employee) => {
const config = {
headers: {
"Content-Type": "application/json",
},
};
try {
const res = await axios.put(
`/api/employees/${employee._id}`,
employee,
config
);
dispatch({ type: UPDATE_EMPLOYEE, payload: res.data });
} catch (err) {
dispatch({
type: EMPLOYEE_ERROR,
payload: err.response.msg,
});
}
dispatch({ type: UPDATE_EMPLOYEE, payload: employee });
};
//Clear Employees
const clearEmployees = () => {
dispatch({ type: CLEAR_EMPLOYEES });
};
//Set Current Employees
const setCurrent = (employee) => {
dispatch({ type: SET_CURRENT, payload: employee });
};
//Clear Current Employee
const clearCurrent = () => {
dispatch({ type: CLEAR_CURRENT });
};
//Filter Employees
const filterEmployees = (text) => {
dispatch({ type: FILTER_EMPLOYEES, payload: text });
};
//Clear Filter
const clearFilter = (text) => {
dispatch({ type: CLEAR_FILTER });
};
return (
<EmployeesContext.Provider
value={{
employees: state.employees,
current: state.current,
filtered: state.filtered,
error: state.error,
loading: state.loading,
callAPI,
getEmployees,
addEmployee,
deleteEmployee,
clearEmployees,
setCurrent,
clearCurrent,
updateEmployee,
filterEmployees,
clearFilter,
}}
>
{props.children}
</EmployeesContext.Provider>
);
};
export default EmployeesState;
// // gives me undefined on console
// const getEmployees = () => {
// axios
// .get("http://localhost:5000/employees")
// .then((res) => dispatch({ type: GET_EMPLOYEES, payload: res }))
// .catch((err) => {
// dispatch({
// type: EMPLOYEE_ERROR,
// });
// });
// };
Home.js
import React, { Fragment } from "react";
import Search from "../employees/Search";
import Employees from "../employees/Employees";
const Home = () => {
return (
<>
<Search />
<Employees />
</>
);
};
export default Home;
Employees.js
import React, { useContext, useEffect } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import EmployeeItem from "./EmployeeItem";
import { v4 as uuidv4 } from "uuid";
import EmployeesContext from "../../contexts/employees/employeesContext";
import Spinner from "../layout/Spinner";
const Employees = () => {
const employeesContext = useContext(EmployeesContext);
const {
employees,
filtered,
getEmployees,
callAPI,
loading,
} = employeesContext;
useEffect(() => {
// callAPI();
getEmployees();
// eslint-disable-next-line
console.log(employees);
console.log(getEmployees());
console.log(callAPI());
}, []);
return (
<div>
<>
{[employees].map((employee) => (
<EmployeeItem key={uuidv4()} employee={employee} />
))}
</>
</div>
);
employeesReducer.js
import {
GET_EMPLOYEES,
ADD_EMPLOYEE,
DELETE_EMPLOYEE,
SET_CURRENT,
CLEAR_CURRENT,
UPDATE_EMPLOYEE,
FILTER_EMPLOYEES,
CLEAR_FILTER,
EMPLOYEE_ERROR,
CLEAR_EMPLOYEES,
} from "../types";
export default (state, action) => {
switch (action.type) {
case GET_EMPLOYEES:
return {
...state,
employees: action.payload,
loading: false,
};
case ADD_EMPLOYEE:
return {
...state,
employee: [action.payload, ...state.employees],
loading: false,
};
case UPDATE_EMPLOYEE:
return {
...state,
employees: state.employees.map((employee) =>
employee._id === action.payload._id ? action.payload : employee
),
loading: false,
};
case DELETE_EMPLOYEE:
return {
...state,
employees: state.employees.filter(
(employee) => employee._id !== action.payload
),
loading: false,
};
case CLEAR_EMPLOYEES:
return {
...state,
employees: null,
filtered: null,
error: null,
current: null,
};
case SET_CURRENT:
return {
...state,
current: action.payload,
};
case CLEAR_CURRENT:
return {
...state,
current: null,
};
case FILTER_EMPLOYEES:
return {
...state,
filtered: state.employees.filter((employee) => {
const regex = new RegExp(`${action.payload}`, "gi");
return employee.name.match(regex) || employee.email.match(regex);
}),
};
case CLEAR_FILTER:
return {
...state,
filtered: null,
};
case EMPLOYEE_ERROR:
return {
...state,
error: action.payload,
};
default:
return state;
}
};
You need to await for the response
const res = await axios.get("http://localhost:5000/employees");
dispatch({ type: GET_EMPLOYEES, payload: res });
or
axios.get("http://localhost:5000/employees")
.then(res => {
dispatch({ type: GET_EMPLOYEES, payload: res });
})
y'all, I'm trying to create a signup and login local-Strategy with passport and have been seeing a PROXY ERROR:. I thought I was returning all possible endings for the functions but maybe I'm missing something? I'm new to development and am going crazy haha... Any help is much appreciated, also let me know if I missed adding pertinent code. (I did not add the return block from the react component, I assumed it unnecessary). I am importing my strategies through a strategy index.js (also did not include).
SignupStratagy.js / local strategy
const Strategy = require("passport-local").Strategy;
const User = require("../models/User");
// for password encryption;
const bcrypt = require("bcrypt");
const saltRounds = 10;
const SignupStrategy = new Strategy({ passReqToCallback: true }, function (
req,
username,
password,
done
) {
// console.log(username, password);
const encryptedPass = bcrypt.hashSync(password, saltRounds);
// console.log("encryptedPassword", encryptedPass);
const phone = req.body.phone;
const email = req.body.email;
const street = req.body.street;
const city = req.body.city;
const state = req.body.state;
const zip = req.body.zip;
const isAdmin = req.body.isAdmin;
User.findOne({ username: username }, (err, user) => {
// console.log("SignupStrategy.js / req:", req.body);
if (err) {
return done(err, user);
}
if (user) {
return done("User Name is already taken:", user);
}
})
// .lean()
// .exec();
// console.log("SignupStrategy.js / encrypted password:", encryptedPass);
let newUser = {
username,
password: encryptedPass,
phone,
email,
street,
city,
state,
zip,
isAdmin,
};
User.create(newUser, (error, newUser) => {
if (error) {
return done(error, null);
}
// delete the user password before it is sent back to the front-end;
newUser.password = undefined;
delete newUser.password;
return done(null, newUser);
});
});
module.exports = SignupStrategy;
apiRoute.js / route for signup
const router = require("express").Router();
const db = require("../models");
const passport = require("../config");
// const isAuthenticated = require("../config/middleware/isAuthenticated");
// USER SIGN-UP ROUTE
router.post("/api/signup", function (req, res, next) {
// console.log(req.body);
passport.authenticate("local-signup", (error, user) => {
// console.log("apiRoutes.js / error:", error, "apiRoutes.js / user:", user)
if (error)
return res.status(500).json({
message: error,
});
else {
return res.status(200).json(user);
}
})(req, res, next);
});
Signup / react component
import React, { useState } from "react";
import axios from "axios";
import { Redirect, Link } from "react-router-dom";
import chip from "../../images/chipper/chipperOne.png";
import "./style.css";
function Signup() {
const [signupState, setSignupState] = useState({
username: "",
password: "",
phone: "",
email: "",
street: "",
city: "",
state: "",
zip: "",
key: "",
redirect: false,
adminRedirect: false,
isAdmin: false,
});
const onChange = (e) => {
// console.log("working")
// console.log(typeof e.target.type)
if (e.target.type === "checkbox") {
if (signupState.isAdmin === false) {
setSignupState({
...signupState,
isAdmin: true,
})
} else {
setSignupState({
...signupState,
isAdmin: false,
});
}
} else {
setSignupState({
...signupState,
[e.target.name]: e.target.value,
});
}
};
const onSubmit = async (e) => {
e.preventDefault();
if (signupState.isAdmin === true) {
const response = await axios.post("/api/admin-sign-up", {
key: signupState.key,
});
console.log(response.status);
if (response.status === 500) {
console.log(response);
return;
}
if (response.status === 200) {
console.log(response.status);
setSignupState({
...signupState,
adminRedirect: true,
});
}
}
// console.log(`onSubmit ${signupState}`);
axios.post("/api/signup", {
username: signupState.username,
password: signupState.password,
phone: signupState.phone,
email: signupState.email,
street: signupState.street,
city: signupState.city,
state: signupState.state,
zip: signupState.zip,
isAdmin: signupState.isAdmin,
})
.then((res) => {
console.log(res);
if (res.data) {
console.log(`Sign-in Successful`);
setSignupState({
...signupState,
redirect: true,
});
}
})
.catch((err) => {
if (err) console.log(`Sign-Up server error ${err}`);
});
};
ERROR:
Proxy error: Could not proxy request /api/signup from localhost:3000 to http://localhost:3001.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
I'm writing a program where the user inputs a number into a React frontend and a Node.js Express backend gets all possible prime numbers under the user number and responds back with the median element of that prime number array.
Server works and the frontend successfully sends a number to the server, but the server response, when I print it in the console, is:
Promise { <state>: "pending" }
undefined
What am I doing wrong?
Frontend React component:
import React, {Component} from 'react';
class NumberInputField extends Component {
constructor() {
super();
this.state = {
number: 0,
errorText: ''
}
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({[e.target.name]:e.target.value});
}
onError(errText) {
this.setState((previousState, props) => {
return { errorText: errText}
})
}
onSubmit(e) {
e.preventDefault();
console.log("> Submitting form");
//console.log(this.state);
fetch('http://localhost:3000/setprime', {
method: 'POST',
body: JSON.stringify(this.state),
})
.then(r => {
console.log(r.json());
})
.then(data => {
console.log(data);
})
.catch(e => {
console.log(e);
this.onError(e.toString());
})
}
render() {
return (
<div>
<form onSubmit={this.onSubmit}>
<input type="text" name="number" onChange={this.onChange}/>
<input type="submit" value="Submit"/>
</form>
<p className="errorLabel">{this.state.errorText}</p>
</div>
);
}
}
export default NumberInputField;
server.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var serverhelpers = require("./serverhelpers");
var cors = require("cors");
app.use(cors());
app.use ( bodyParser.json( { type: "*/*" } ));
app.post("/setprime", (req, res) => {
console.log(req.body);
console.log("Received number " + req.body.number + " from frontend");
let primes = getAllPrimes(req.body.number);
let median = getMedianArray(primes);
console.log("Primes: " + primes);
console.log("Median: " + median);
res.setHeader("Content-type", "application/json");
return res.send(median);
});
app.listen(3000);
console.log("Server listening on port 3000.");
Thank you
the problem is with :
.then(r => {
console.log(r.json());
})
the return value of r.json() is Promise
youhave to return it :
.then(r => {
//console.log(r.json());
return r.json();
})
you should see data logged afterwards.
Im currently trying to send a message from my server side and display it in my react front end.
I have tried everything to display the message I use with res.send() but the react fails to receive it can anyone help me point out what I am doing wrong here?
Sample of the front end:
import React, {Component} from 'react';
import axios from 'axios';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
export default class CreateFile extends Component {
constructor(props) {
super(props);
this.onChangeFileDescription = this.onChangeFileDescription.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
file_description: '',
};
this.handleSelect = this.handleSelect.bind(this);
axios
.get("http://localhost:4000/api/isloggedin")
.then(res => {
if (!res.data) {
return this.setState({isloggedin: false});
}
});
}
onChangeFileDescription(e) {
this.setState({
file_description: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`File Description: ${this.state.file_description}`);
const newFile = {
file_description: this.state.file_description,
}
axios.post('http://localhost:4000/files/add', newFile)
.then(res => console.log(res.data));
this.setState({
file_description: '',
})
}
render() {
return this.state.isloggedin ? (
<div style={{marginTop: 20}}>
<h3>Upload a New File</h3>
<Tabs
id="controlled-tab-example"
activeKey={this.state.key}
onSelect={key => this.setState({key})}
>
<Tab eventKey="audio" title="Audio">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>File Description: </label>
<input type="text"
className="form-control"
value={this.state.file_description}
onChange={this.onChangeFileDescription}
/>
</div>
</Tabs>
</div>
) : (
<h3>Please login</h3>
);
}
}
This is the server side:
Im checking if the submitted form is empty and if it is sending a error back asking users to fill the required field.
const express = require('express');
const bodyParser = require('body-parser');
const fileRoutes = express.Router();
const File = require("../models/fileHandler");
module.exports = function(app) {
app.use(bodyParser.json());
fileRoutes.route('/').get(function (req, res) {
File.find(function (err, files) {
if (err) {
console.log(err);
} else {
res.json(files);
}
});
});
fileRoutes.route('/:id').get(function (req, res) {
let id = req.params.id;
File.findById(id, function (err, file) {
res.json(file);
});
});
fileRoutes.route('/add').post(function (req, res) {
console.log(req.body.file_description);
if (req.body.file_description === ""){
console.log("its empty!");
var result = {"data" :"hello everybody !"}
res.status(200).json({'description': 'description is needed'});
return res.send(result);
}
let file = new File(req.body);
file.save()
.then(file => {
res.status(200).json({'file': 'file added successfully'});
})
.catch(err => {
res.status(400).send('adding new file failed');
});
});
fileRoutes.route('/update/:id').post(function (req, res) {
File.findById(req.params.id, function (err, file) {
if (!file)
res.status(404).send('data is not found');
else
file.file_description = req.body.file_description;
file.file_size = req.body.file_size;
file.file_duration = req.body.file_duration;
file.file_artist = req.body.file_artist;
file.file_bitrate = req.body.file_bitrate;
file.file_codec = req.body.file_codec;
file.file_audioChannels = req.body.file_audioChannels;
file.file_dimensions = req.body.file_dimensions;
file.file_tag = req.body.file_tag;
file.file_colorProfile = req.body.file_colorProfile;
file.file_extension = req.body.file_extension;
file.file_employeeResponsible = req.body.file_employeeResponsible;
file.file_editActive = req.body.file_editActive;
file.file_completed = req.body.file_completed;
file.save().then(file => {
res.json('File updated');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
app.use('/files', fileRoutes);
};
Ok after some digging I managed to solve this issue.
I thought i posted here in case anyone had a similar problem.
So what I did was to check everything with express validator and if there was any problem to send it to the react front end.
And in react front end if the there is any problem received regarding that specific field it will display it on top of the input field.
hope this helps.
{this.state.errors &&
this.state.errors.file_description && <p>{this.state.errors.file_description.msg}
And the complete snippet of the react front end.
import React, {Component} from 'react';
import axios from 'axios';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
export default class CreateFile extends Component {
constructor(props) {
super(props);
this.onChangeFileDescription = this.onChangeFileDescription.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
file_description: ''
};
this.handleSelect = this.handleSelect.bind(this);
axios
.get("http://localhost:4000/api/isloggedin")
.then(res => {
if (!res.data) {
return this.setState({isloggedin: false});
}
});
}
onChangeFileDescription(e) {
this.setState({
file_description: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`File Description: ${this.state.file_description}`);
const newFile = {
file_description: this.state.file_description
}
axios.post('http://localhost:4000/files/add', newFile)
.then(result => {
if (result.data.errors) {
return this.setState(result.data);
}
return this.setState({
userdata: result.data,
errors: null,
success: true
});
});
this.setState({
file_description: ''
})
}
render() {
return this.state.isloggedin ? (
<div style={{marginTop: 20}}>
<h3>Upload a New File</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>File Description: </label>
<input type="text"
className="form-control"
value={this.state.file_description}
onChange={this.onChangeFileDescription}/>
{this.state.errors &&
this.state.errors.file_description && <p>{this.state.errors.file_description.msg}</p>}
</div>
<label className="form-check-label">Yes</label>
</div>
</div>
<div className="form-group">
<input type="submit" value="Upload File" className="btn btn-primary"/>
</div>
</form>
</Tab>
</Tabs>
</div>
) : (
<h3>Please login</h3>
);
}
}
for the backend I have also tweaked it so if there is any problem it will post that back to the react front end validating with Express validator and using the normal route and post methods.
const express = require('express');
var { check, validationResult } = require("express-validator/check");
const bodyParser = require('body-parser');
const fileRoutes = express.Router();
const File = require("../models/fileHandler");
module.exports = function(app) {
const fileValidation = [
check("file_description")
.not()
.isEmpty()
.withMessage("Description required"),
];
app.use(bodyParser.json());
fileRoutes.route('/').get(function (req, res) {
File.find(function (err, files) {
if (err) {
console.log(err);
} else {
res.json(files);
}
});
});
fileRoutes.route('/:id').get(function (req, res) {
let id = req.params.id;
File.findById(id, function (err, file) {
res.json(file);
});
});
fileRoutes.route('/add').post(fileValidation, function (req, res) {
var errors = validationResult(req);
if (!errors.isEmpty()) {
return res.send({ errors: errors.mapped() });
}else{
console.log("its empty!");
let file = new File(req.body);
file.save()
.then(file => {
res.status(200).json({'file': 'file added successfully'});
})
.catch(err => res.send(err));
}
});
fileRoutes.route('/update/:id').post(function (req, res) {
File.findById(req.params.id, function (err, file) {
if (!file)
res.status(404).send('data is not found');
else
file.file_description = req.body.file_description;
file.save().then(file => {
res.json('File updated');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
app.use('/files', fileRoutes);
};