Express routing trouble - POST 404 (Not Found) - javascript

Something just isn't connecting properly when I attempt to use routes specified within login.js for login.component.js.
It's strange because when I change axios.post('http://localhost:5000/login/add3', user) (/add3) to axios.post('http://localhost:5000/login/add', user) (/add) it performs the POST correctly, which leads me to believe it either isn't connected or it's connected to a different route than I specified.
Link to 404 error
Relevent Files: app.js, login.js, login.component.js, login.model.js
app.js ↓
import "bootstrap/dist/css/bootstrap.min.css";
import { BrowserRouter as Router, Route} from "react-router-dom";
import Navbar from "./components/navbar.component"
import ExercisesList from "./components/exercises-list.component";
import EditExercise from "./components/edit-exercise.component";
import CreateExercise from "./components/create-exercise.component";
import CreateUser from "./components/create-user.component";
import LoginUser from "./components/login.component";
function App() {
return (
<Router>
<div className="container">
<Navbar />
<br/>
<Route path="/" exact component={ExercisesList} />
<Route path="/edit/:id" component={EditExercise} />
<Route path="/create" component={CreateExercise} />
<Route path="/user" component={CreateUser} />
<Route path="/login" component={LoginUser} />
</div>
</Router>
);
}
export default App;
login.js ↓
let Login = require('../models/login.model');
router.route('/').get((req, res) => {
Login.find()
.then(users => res.json(users))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add3').post((req, res) => {
const username = req.body.username;
const password = req.body.password;
const newUser = new Login({
username,
password
});
newUser.save()
.then(() => res.json('User added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router;
login.component.js ↓
import axios from 'axios';
export default class LoginUser extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangePassword = this.onChangePassword.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username: '',
password: ''
}
}
onChangeUsername(e) {
this.setState({
username: e.target.value
})
}
onChangePassword(e) {
this.setState({
password: e.target.value
})
}
onSubmit(e) {
e.preventDefault();
const user = {
username: this.state.username,
password: this.state.password
}
console.log(user);
axios.post('http://localhost:5000/login/add3', user)
.then(res => console.log(res.data));
}
render() {
return (
<div>
<h3>Login</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<input type="text"
required
className="form-control"
placeholder="Username"
value={this.state.username}
onChange={this.onChangeUsername}
/>
<input type="text"
required
className="form-control"
placeholder="Password"
value={this.state.password}
onChange={this.onChangePassword}
/>
</div>
<div className="form-group">
<input type="submit" value="Login" className="btn btn-primary" />
</div>
</form>
</div>
)
}
}
login.model.js ↓
const Schema = mongoose.Schema;
const loginSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
}
});
const Login = mongoose.model('Login', loginSchema);
module.exports = Login;
Sorry if this is a common question or if there's just a super easy answer, I'm clearly new to ReactJS so I figured I'd just ask others who are far more knowledgeable on the subject

I solved this problem on accident... for future reference, just restart the connection to your database! Didn't know that could cause an issue, but here's to learning.

Related

"No routes matched location"

I am developing a simple application of notes, and when I try to edit the notes, I get the error "No routes matched location id ..."
What am I doing wrong?
I try to get the id of the note by params
This is my code:
Notes.js:
import React from "react";
import Header from "./notes/Header";
import Home from "./notes/Home";
import CrearNota from "./notes/CrearNota";
import EditarNota from "./notes/EditarNota";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
export default function Notes({ setIsLogin }) {
return (
<header>
<BrowserRouter>
<Header setIsLogin={setIsLogin} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/create" element={<CrearNota />} />
<Route path="/edit/:id" element={<EditarNota />} />
</Routes>
</BrowserRouter>
</header>
);
}
And EditarNotas.js:
import { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
export default function EditarNota(match) {
const [note, setNote] = useState({
title: "",
content: "",
date: "",
id: "",
});
const navigate = useNavigate();
useEffect(() => {
const getNote = async () => {
const token = localStorage.getItem("tokenStore");
if (match.params.id) {
const res = await axios.get(`/api/notes/${match.params.id}`, {
headers: { Authorization: token },
});
console.log(match.params.id);
console.log(res);
setNote({
title: res.data.title,
content: res.data.content,
date: res.data.date,
id: res.data._id,
});
}
};
getNote();
}, [match.params.id]);
const onChangeInput = (e) => {
const { name, value } = e.target;
setNote({ ...note, [name]: value });
};
const editNote = async (e) => {
e.preventDefault();
try {
const token = localStorage.getItem("tokenStore");
if (token) {
const { title, content, date, id } = note;
const newNote = {
title,
content,
date,
};
await axios.post(`api/notes/${id}`, newNote, {
headers: { Authorization: token },
});
return navigate.push("/");
}
} catch (err) {
window.location.href = "/";
}
};
return (
<>
<h2>Crear nota</h2>;
<form on onSubmit={editNote} autoComplete="off">
<div>
<label htmlFor="title">Title</label>
<input
type="text"
value={note.title}
id="title"
name="title"
required
onChange={onChangeInput}
/>
</div>
<div>
<label htmlFor="content">Content</label>
<input
type="text"
value={note.content}
id="content"
name="content"
required
rows="10"
onChange={onChangeInput}
/>
</div>
<div>
<label htmlFor="date">Date: {note.date}</label>
<input
type="date"
id="date"
name="date"
required
onChange={onChangeInput}
/>
</div>
<button type="submit">Guardar</button>
</form>
</>
);
}
It is my first post, if I have done something wrong, sorry and let me know.
Thanks in advance.
From your code it seems match is a props.
instead of accessing it like this:
export default function EditarNota(match)
try spreading the props like this:
export default function EditarNota({match})
or this way:export default function EditarNota(props)
then where ever you have match change it to props.match.
Instead of navigate.push('/'), navigate('/')

Cannot read property 'push' of undefined on the login page

I'm doing a login page with JWT and trying to redirect the page once log in to the home using this.props.history.push("/") but I get this typeError: Cannot read property 'push'of undefined. I don't know what I am doing wrong.
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "cihemzine#gmail.com",
password: "test",
};
}
handleChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
});
};
login = () => {
const { email, password} = this.state;
axios("/users/login", {
method: "POST",
data: {
email,
password
},
})
.then((response) => {
localStorage.setItem('token', response.data.token);
console.log(response.data);
this.props.history.push("/");
})
.catch((error) => {
console.log(error);
});
};
render() {
return (
<div>
<div className="container">
<input value={this.state.email} onChange={this.handleChange} className="form-control mb-2 mt-4"name="email" type="text"placeholder="Your email" />
<input value={this.state.password} onChange={this.handleChange} className="form-control mb-2"name="password" type="password" placeholder="Your password" /><br></br>
<button onClick={this.login}className="text-center btn btn-light">LOGIN</button>
</div>
</div>
)
}
}
export default Login;
If you have nothing like 'history, match etc' in your props you need to check that you use your login component as Route
<Route path ='' component={Login} />
If you don't use Login in such way and can't for some reasons.
You can use HOC or hook for you component to add history to your component.
import { useHistory } from "react-router-dom"
or
import { withRouter } from "react-router";

ReactJS API authentication : Cannot update during an existing state transition

I am building an app with ReactJS that authenticate users through a Laravel API.
This is a very simple app. And the authentication part is working well. But after authentication when I try to change the state I am getting this error.
Cannot update during an existing state transition
The App I am trying to build is a very simple one. After the app makes an API call to authenticate the user, it must get the user's data from the API response and pass those responses to the component set for logged in users.
I made some search on the error Cannot update during an existing state transition. All the answers I am getting are telling me not to setState inside of a render. I am not doing that.
Here is my code
App.jsx
//...
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
user: {}
};
}
_loginUser = (email, password) => {
var formData = new FormData();
formData.append("email", email);
formData.append("password", password);
axios
.post("http://localhost:8000/api/user/login", formData)
.then(response => {
console.log(response);
return response;
})
.then(json => {
if (json.data.success) {
let userData = {
first_name: json.data.data.first_name,
name: json.data.data.name,
id: json.data.data.email,
email: json.data.data.email,
auth_token: json.data.data.auth_token,
timestamp: new Date().toString()
};
let appState = {
isLoggedIn: true,
user: userData
};
//Save app state with user date in local storage
localStorage["appState"] = JSON.stringify(appState);
this.setState({
isLoggedIn: appState.isLoggedIn,
user: appState.user
});
} else {
$("#feedbacks").html(
`<span className="alert alert-danger">Login Failed: ${
json.data.data
}</span>`
);
}
$("#email-login-btn")
.removeAttr("disabled")
.html("Login");
})
.catch(error => {
$("#feedbacks").html(
`<span className="alert alert-danger">An Error Occured</span>`
);
$("#email-login-btn")
.removeAttr("disabled")
.html("Login");
});
};
componentDidMount() {
let state = localStorage["appState"];
if (state) {
let AppState = JSON.parse(state);
console.log(AppState);
this.setState({
isLoggedIn: AppState.isLoggedIn,
user: AppState
});
}
}
render() {
if (
!this.state.isLoggedIn &&
this.props.location.pathname !== "/app/login"
) {
this.props.history.push("/app/login");
}
if (
this.state.isLoggedIn &&
(this.props.location.pathname === "/app/login" ||
this.props.location.pathname === "/app/register")
) {
this.props.history.push("/");
}
return (
<Switch data="data">
<Route
exact
path="/"
render={props => (
<Home
{...props}
logOut={this._logoutUser}
isLoggedIn={this.state.isLoggedIn}
user={this.state.user}
/>
)}
/>
<Route
path="/app/login"
render={props => (
<Login {...props} loginUser={this._loginUser} />
)}
/>
</Switch>
);
}
}
const AppContainer = withRouter(props => <App {...props} />);
render(
<BrowserRouter>
<AppContainer />
</BrowserRouter>,
document.getElementById("root")
);
Login.jsx
const Login = ({ history, loginUser = f => f }) => {
console.log(history);
let _email, _password;
const handleLogin = e => {
e.preventDefault();
loginUser(_email.value, _password.value);
};
return (
<div>
<div id="wrapper" className="formWrapper">
<form method="post" action="#" onSubmit={handleLogin}>
<div className="fields">
<div className="field">
<label htmlFor="email">Your Email</label>
<input
ref={input => (_email = input)}
autoComplete="off"
id="email"
name="email"
type="text"
className="center-block"
placeholder="email"
/>
</div>
<div className="field">
<label htmlFor="password">Your Password</label>
<input
ref={input => (_password = input)}
autoComplete="off"
id="password-input"
name="password"
type="password"
className="center-block"
placeholder="password"
/>
</div>
</div>
<div className="actions login">
<button
type="submit"
className="primary"
id="email-login-btn"
>
<span className="icon fa-user" /> Login
</button>
</div>
</form>
</div>
<div id="blur" />
<div id="bg" />
</div>
);
};
export default Login;
The _login method handles the form submit. And within that method, I setState the user once authentication is valid. Apparently, that is where the error is coming from. That generates the error :
Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
So I need to know where is the right place to change the value of the state 'user'.
Can someone help, please?

React Router will not redirect based on state

In the code, it reaches the isRegistered function, I know this as I have it console.log state. The state of registered is equal to true. So therefore based on the code it should redirect to /login but it is not.
import React from 'react'
import "./Register.css";
import {BrowserRouter as Route, Redirect, Link} from 'react-router-dom'
const initialUser = {
username: "",
email: "",
password: "",
password2: "",
name: ""
}
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
user: initialUser,
registered: ''
};
}
onUsernameChange = event => {
this.setState({ username: event.target.value });
};
onNameChange = event => {
this.setState({ name: event.target.value });
};
onEmailChange = event => {
this.setState({ email: event.target.value });
};
onPasswordChange = event => {
this.setState({ password: event.target.value });
};
onPassword2Change = event => {
this.setState({ password2: event.target.value });
};
isRegistered() {
const { registered } = this.state;
console.log(registered, 'here', this.state)
if (registered) {
return (
<Redirect to='/login' />
)
}
}
onRegister = () => {
fetch("http://localhost:3000/register", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
username: this.state.username,
password: this.state.password,
password2: this.state.password2
})
})
.then(res => res.json())
.then(data => {
console.log(data.isRegistered);
if (data.isRegistered) {
this.setState({registered: true})
this.isRegistered();
}
})
};
render() {
return <div className="login-page">
<div className="form">
<form className="login-form">
<input type="text" placeholder="name" onChange={this.onNameChange} />
<input type="text" placeholder="username" onChange={this.onUsernameChange} />
<input type="text" placeholder="email" onChange={this.onEmailChange} />
<input type="password" placeholder="password" onChange={this.onPasswordChange} />
<input type="password" placeholder="confirm password" onChange={this.onPassword2Change} />
<button className="bluecolor" onClick={this.onRegister}>
Register
</button>
<p className="message">
Have an account? Login
</p>
</form>
</div>
</div>;
}
}
export default Register;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
It reaches all the way to the if statement in isRegistered(). So I assume it is the redirect component that is wrong but I cannot figure it out for the life of me.
//UPDATE
This is now what I have in it
import React from 'react'
import "./Register.css";
import {BrowserRouter as Route, Redirect, withRouter} from 'react-router-dom'
const initialUser = {
username: "",
email: "",
password: "",
password2: "",
name: ""
}
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
user: initialUser,
registered: ''
};
}
onUsernameChange = event => {
this.setState({ username: event.target.value });
};
onNameChange = event => {
this.setState({ name: event.target.value });
};
onEmailChange = event => {
this.setState({ email: event.target.value });
};
onPasswordChange = event => {
this.setState({ password: event.target.value });
};
onPassword2Change = event => {
this.setState({ password2: event.target.value });
};
isRegistered() {
const { registered } = this.state;
console.log(registered, 'here', this.state)
if (registered) {
this.props.history.push('/login')
}
}
onRegister = () => {
fetch("http://localhost:3000/register", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
username: this.state.username,
password: this.state.password,
password2: this.state.password2
})
})
.then(res => res.json())
.then(data => {
console.log(data.isRegistered);
if (data.isRegistered) {
this.setState({registered: true})
this.isRegistered();
}
})
};
render() {
return <div className="login-page">
<div className="form">
<form className="login-form">
<input type="text" placeholder="name" onChange={this.onNameChange} />
<input type="text" placeholder="username" onChange={this.onUsernameChange} />
<input type="text" placeholder="email" onChange={this.onEmailChange} />
<input type="password" placeholder="password" onChange={this.onPasswordChange} />
<input type="password" placeholder="confirm password" onChange={this.onPassword2Change} />
<button className="bluecolor" onClick={this.onRegister}>
Register
</button>
<p className="message">
Have an account? Login
</p>
</form>
</div>
</div>;
}
}
export default withRouter(Register);
And this is the main App.js
import React, { Component } from 'react';
import RegisterFull from "./Components/Register/RegisterFull";
import LoginFull from "./Components/Login/LoginFull";
import HomeFull from "./Components/Home/HomeFull";
import FullContact from "./Components/Contact/FullContact";
import './App.css';
import './Components/flex.css'
import {BrowserRouter as Router, Route} from "react-router-dom";
class App extends Component {
constructor(props) {
super(props);
this.state = {
signedIn: false
}
}
loginUser = () => {
this.setState({signedIn: true})
}
render() {
return (
<Router>
<div>
<Route exact={true} path='/' component={HomeFull}/>
<Route path='/contact' component={FullContact} />
<Route path='/login' component={LoginFull} />
<Route path='/register' component={RegisterFull} />
<Route path='/about' component={HomeFull} />
</div>
</Router>
)
}
}
export default App;
You cannot return Redirect element in render like this by invoking another method in component lifecycles or methods.
You need to wrap your component with withRouter HOC which provides history props.
import {BrowserRouter as Route,, withRouter, Redirect, Link} from 'react-router-dom'
export default withRouter(Register);
and if you want to navigate programmatically :
isRegistered = () => {
const { registered } = this.state;
console.log(registered, 'here', this.state)
if (registered) {
this.props.history.push('/login)
}
}
Some improvements in your code you could make. Here is my suggestion. you don't need to bind anything. You are using latest React. How I know? You are doing onUsernameChange = evnet => {} not onUsernameChange(event){}. Overall #Sakhi Mansoor is right.
import React from "react";
import "./Register.css";
import {
BrowserRouter as Route,
withRouter,
Redirect,
Link
} from "react-router-dom";
const initialUser = {
username: "",
email: "",
password: "",
password2: "",
name: ""
};
class Register extends React.Component {
constructor(props) {
super(props);
this.state = {
user: initialUser,
registered: ""
};
}
handleChange = event => {
this.setState({
user: {
...this.state.user,
[event.target.name]: event.target.value
}
});
};
isRegistered = () => {
const { registered } = this.state;
console.log(registered, "here", this.state);
if (registered) {
this.props.history.push("/login");
}
};
onRegister = event => {
event.preventDefault();
fetch("http://localhost:3000/register", {
method: "post",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(this.state.user)
})
.then(res => res.json())
.then(data => {
console.log(data.isRegistered);
if (data.isRegistered) {
this.setState({ registered: true });
this.isRegistered();
}
});
};
render() {
return (
<div className="login-page">
<div className="form">
<form className="login-form" onSubmit={this.onRegister}>
<input
type="text"
placeholder="name"
name="name"
value={this.state.user.name}
onChange={this.handleChange}
/>
<input
type="text"
placeholder="username"
name="username"
value={this.state.user.username}
onChange={this.handleChange}
/>
<input
type="text"
placeholder="email"
name="email"
value={this.state.user.email}
onChange={this.handleChange}
/>
<input
type="password"
placeholder="password"
name="password"
value={this.state.user.password}
onChange={this.handleChange}
/>
<input
type="password"
placeholder="confirm password"
name="password2"
value={this.state.user.password2}
onChange={this.handleChange}
/>
<button className="bluecolor" type="submit">
Register
</button>
<p className="message">
Have an account? Login
</p>
</form>
</div>
</div>
);
}
}
export default withRouter(Register);
Here is a simple example of how to redirect on a button click.Hope this might help you
import React, { Component } from "react";
import { BrowserRouter,Route,Switch } from 'react-router-dom'
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Sample}/>
<Route path="/test" exact render={()=>(<p>Test</p>)}/>
</Switch>
</BrowserRouter>
)
}
}
class Sample extends React.Component {
constructor(props) {
super(props)
this.Click = this.Click.bind(this) // you need to bind the method
}
Click() {
this.props.history.push('/test');
}
render() {
return(
<button onClick={this.Click}>Click</button>
)
}
}
export default App;

_this2.props.signup is not a function in React Redux app

Please note that I've already checked answers in this question and nothing seems to work.
I'm using this repo as a boilerplate. Instead of firebase database, I'm trying to send username and email with the firebase auth userid , to the node server. I created an action creator signup to handle this.
This is signup.js action creator
import * as types from '../constants/action_types';
import axios from 'axios';
export const signup = (user) => {
console.log(user);
return async dispatch => {
try {
const response = await axios.get('http://localhost:5000/api/user/register', user)
const data = await {response};
dispatch({
type : types.SIGN_UP,
payload : data.fromback
})
} catch (error) {
console.lot(error)
}
}
}
Then I've connected it with the component with mapDispatchToProps., So,under the SignUpPage component, React dev tools shows signup as a function. But when it get triggers, it gives an error saying _this2.props.signup is not a function Why's that ?
This is my SignUpPage component
import React, { Component } from 'react';
import {
Link,
withRouter,
} from 'react-router-dom';
import { auth } from '../../firebase';
import * as routes from '../../constants/routes';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {signup} from './../../actions/signup';
const SignUpPage = ({ history }) =>
<div>
<h1>SignUp</h1>
<SignUpForm history={history} />
</div>
const updateByPropertyName = (propertyName, value) => () => ({
[propertyName]: value,
});
const INITIAL_STATE = {
username: '',
email: '',
passwordOne: '',
passwordTwo: '',
error: null,
};
class SignUpForm extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = (event) => {
const {
username,
email,
passwordOne,
} = this.state;
const {
history,
} = this.props;
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
this.props.signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});
event.preventDefault();
}
render() {
const {
username,
email,
passwordOne,
passwordTwo,
error,
} = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === '' ||
username === '' ||
email === '';
return (
<form onSubmit={this.onSubmit}>
<input
value={username}
onChange={event => this.setState(updateByPropertyName('username', event.target.value))}
type="text"
placeholder="Full Name"
/>
<input
value={email}
onChange={event => this.setState(updateByPropertyName('email', event.target.value))}
type="text"
placeholder="Email Address"
/>
<input
value={passwordOne}
onChange={event => this.setState(updateByPropertyName('passwordOne', event.target.value))}
type="password"
placeholder="Password"
/>
<input
value={passwordTwo}
onChange={event => this.setState(updateByPropertyName('passwordTwo', event.target.value))}
type="password"
placeholder="Confirm Password"
/>
<button disabled={isInvalid} type="submit">
Sign Up
</button>
{ error && <p>{error.message}</p> }
</form>
);
}
}
const SignUpLink = () =>
<p>
Don't have an account?
{' '}
<Link to={routes.SIGN_UP}>Sign Up</Link>
</p>
const mapDispatchToProps = dispatch => bindActionCreators({ signup }, dispatch)
export default connect(null, mapDispatchToProps)(withRouter(SignUpPage));
export {
SignUpForm,
SignUpLink,
};
Its not a prop,
you've imported it as a function,
you can directly use it as function like this
import {signup} from './../../actions/signup';
.....
auth.doCreateUserWithEmailAndPassword(email, passwordOne)
.then(authUser => {
const userid = authUser.user.uid;
const user = { email, userid };
signup(user);
})
.catch(error => {
this.setState(updateByPropertyName('error', error));
});

Categories

Resources