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('/')
Related
I'm trying to route a page to my project that will allow the user to edit an existing data entry within a MongoDB database, however I am getting this error. The intended function of the program is that a user will be able to select an edit button on a specific data entry, which will open a form allowing them to altar that entry's content. It should do this by making a get request using the data's ID, however there is something wrong happening when I try to concatenate the route string, and the data's ID. Here is my Main.js file, my VehiclesList.js file, and my EditVehicles.js file:
Main.js
import React, { Component } from "react";
import "./index.css";
import { Routes, Route } from "react-router-dom";
import VehicleList from "../VehicleList/index";
import AddVehicle from "../addVehicle/index";
import EditVehicle from "../editVehicle";
class Main extends Component {
render() {
return (
<div className="main">
<Routes>
<Route exact path="/" element={<VehicleList />} />
<Route path="/list" element={<VehicleList />} />
<Route path="/addVehicle" element={<AddVehicle />} />
<Route path="/editVehicle/:id" element={<EditVehicle />} />
</Routes>
</div>
);
}
}
export default Main;
VehiclesList.js
import React, { Component, useState } from "react";
import "./index.css";
import axios from "axios";
import { Link } from "react-router-dom";
import VehicleService from "../services/services";
class VehicleList extends Component {
constructor(props) {
super(props);
this.VehicleService = new VehicleService();
this.state = {
vehicles: [],
};
this.deleteVehicle = this.deleteVehicle.bind(this);
}
componentDidMount = () => {
this.getVehicleList();
};
//get all vehicles
getVehicleList() {
axios
.get("http://localhost:5000/vehicles")
.then((res) => {
console.log(res);
this.setState({
vehicles: res.data,
});
})
.catch((err) => {
console.log(err);
});
}
//delete vehicle
deleteVehicle(vehicleId) {
this.VehicleService.deleteVehicle(vehicleId);
this.getVehicleList();
window.location.reload(false);
}
render() {
const { vehicles } = this.state;
return (
<div className="vehicleList">
<table className="vehicleList_table">
<thead>
<tr className="vehicleList_table_head">
<th className="vehicleList_table_head_title">#</th>
<th className="vehicleList_table_head_title">Make</th>
<th className="vehicleList_table_head_title">Model</th>
<th className="vehicleList_table_head_title">Year</th>
<th className="vehicleList_table_head_title">Price</th>
<th className="vehicleList_table_head_title">Status</th>
<th className="vehicleList_table_head_title"></th>
<th className="vehicleList_table_head_title"></th>
</tr>
</thead>
<tbody className="vehicleList_table_body">
{vehicles &&
vehicles.map((vehicle, idx) => {
let status = "";
if (vehicle.isSold) {
status = "Sold";
} else {
status = "Available";
}
return (
<tr key={idx}>
<td className="vehicleList_table_item">{vehicle._id}</td>
<td className="vehicleList_table_item">{vehicle.make}</td>
<td className="vehicleList_table_item">{vehicle.model}</td>
<td className="vehicleList_table_item">{vehicle.year}</td>
<td className="vehicleList_table_item">{vehicle.price}</td>
<td className="vehicleList_table_item">{status}</td>
<td className="vehicleList_table_item">
<Link
to={"/editVehicle/" + vehicle._id}
style={{ fontSize: "1.5rem" }}
className="edit_btn"
>
edit
</Link>
</td>
<td className="vehicleList_table_item">
<button
onClick={() => this.deleteVehicle(vehicle._id)}
className="delete_btn"
>
Delete
</button>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
}
export default VehicleList;
EditVehicles.js
import React, { Component } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
class EditVehicle extends Component {
constructor(props) {
super(props);
this.state = {
make: "",
model: "",
year: "",
price: "",
isSold: "",
};
}
componentDidMount = () => {
this.getVehicleById();
};
//get vehicle by ID
getVehicleById() {
axios
.get(
"http://localhost:5000/vehicles/editVehicle/" +
this.props.match.params.id
)
.then((res) => {
this.setState({
make: res.data.make,
model: res.data.model,
year: res.data.year,
price: res.date.price,
isSold: res.data.isSold,
});
})
.catch((err) => {
console.log(err);
});
}
//handle changes to data
changeHandler = (e) => {
this.setState({ [e.target.name]: e.target.value });
};
//update record on submit
submitHandler = (e) => {
e.preventDefault();
const { make, model, year, price, isSold } = this.state;
axios
.post(
"http://localhost:5000/vehicles/editVehicle/" +
this.props.match.params.id,
{
make: make,
model: model,
year: year,
price: price,
isSold: isSold,
}
)
.then((res) => {
console.log(res);
this.props.history.push("/");
})
.catch((err) => {
console.log(err);
});
};
render() {
return (
<div className="editVehicle">
<form className="editVehicle_form" onSubmit={this.submitHandler}>
<Link to="/" className="back_btn">
Back
</Link>
<h1>Update Vehicle Details</h1>
<p>Please fill out all fields</p>
<input
name="make"
placeholder="Make"
type="text"
value={this.state.make}
onChange={this.changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="model"
placeholder="Model"
type="text"
value={this.state.model}
onChange={this.changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="year"
placeholder="Year"
type="text"
value={this.state.year}
onChange={this.changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="price"
placeholder="Price"
type="text"
value={this.state.price}
onChange={this.changeHandler}
className="editVehicle_form_input"
/>
<br />
<label className="addVehicle_form_radio_label">
Available
<input
name="isSold"
type="radio"
value={false}
onChange={this.changeHandler}
className="editVehicle_form_radio"
/>
</label>
<label className="editVehicle_form_radio_label">
Sold
<input
name="isSold"
type="radio"
value={true}
onChange={this.changeHandler}
className="editVehicle_form_radio"
/>
</label>
<br />
<input type="submit" value="Save" className="editVehicle_submit" />
</form>
</div>
);
}
}
export default EditVehicle;
My Routes to the VehiclesList, AddVehicle and DeleteVehicle pages all work. the only issue I'm running into is routing the EditVehicle page.
at first I was getting the error "Cannot read properties of undefined('params'), and then I changed the route to the EditVehicles page to this:
<Route path="/editVehicle/:id" component={EditVehicle} />
when I did it this way, I got an error back saying that this route did not have an element, and would result in an empty page.
I also tried doing it this way:
<Route path='/editVehicle/:id render={(props) => <EditVehicle {...props} />} />
this too just gave me an error saying that the route did not have an element.
is there an issue in my code that I am not seeing? or is there an easier way to do this?
The error tells you, that you don't have element attribute in Route:
<Route path="/editVehicle/:id" component={EditVehicle} />
Replace component to element
<Route path="/editVehicle/:id" element={<EditVehicle/>} />
You messed up with different versions of React-router-dom implementations.
see docs
Try to add useParams hook from React-router-dom in your EditVehicle component to get id:
let { id } = useParams();
Issue
The "edit vehicle" route is correct:
<Route path="/editVehicle/:id" element={<EditVehicle />} />
The issue is that in react-router-dom#6 there are no longer any route props. In other words, EditVehicle is a class-based component and this.props.match and this.props.history are undefined. It's only when the code attempts to access into this undefined object (i.e. this.props.match.params) that the error is thrown.
Additionally, the history object is no longer directly exposed in RRDv6, you'll need to use the useNavigate hook to access a navigate function.
Solution
You can either convert EditVehicle to a React function component or create a new custom withRouter Higher Order Component so that the route path params can be injected as props like the class component is expecting.
Using custom withRouter HOC
Create a withRouter HOC that can use the React hooks and inject new props for the class component to access.
import { useNavigate, useParams, /* other hooks */ } from 'react-router-dom';
const withRouter = Component => props => {
const navigate = useNavigate();
const params = useParams();
// ... other hooks ...
return (
<Component
{...props}
{...{ navigate, params, /* other props from hooks */ }}
/>
);
};
Decorate the EditVehicle component export:
import withRouter from '../path/to/withRouter';
...
export default withRouter(EditVehicle);
params and navigate (and others) are now injected as props, access accordingly in EditVehicle:
// get vehicle by ID
getVehicleById() {
const { params: { id } } = this.props;
axios.get("http://localhost:5000/vehicles/editVehicle/" + id)
.then((res) => {
const { data: { make, model, year, price, isSold } } = res;
this.setState({ make, model, year, price, isSold });
})
.catch(console.log);
}
// update record on submit
submitHandler = (e) => {
e.preventDefault();
const { make, model, year, price, isSold } = this.state;
const { navigate, params: { id } } = this.props;
axios
.post(
"http://localhost:5000/vehicles/editVehicle/" + id,
{ make, model, year, price, isSold }
)
.then((res) => {
console.log(res);
navigate("/");
})
.catch(console.log);
};
Conversion to React function component
Use the useNavigate and useParams hooks directly
Use React.useState to store the form field values
use React.useEffect to update the state when the id path param updates
Convert all class methods to functions, and remove references to this
Code:
import React, { useEffect, useState } from "react";
import axios from "axios";
import { Link, useParams, useNavigate } from "react-router-dom";
const EditVehicle = () => {
const navigate = useNavigate();
const { id } = useParams();
const [state, setState] = useState({
make: "",
model: "",
year: "",
price: "",
isSold: ""
});
useEffect(() => {
// get vehicle by ID
const getVehicleById = (id) => {
axios
.get("http://localhost:5000/vehicles/editVehicle/" + id)
.then((res) => {
const { make, model, year, price, isSold } = res.data;
setState({ make, model, year, price, isSold });
})
.catch(console.log);
};
getVehicleById(id);
}, [id]);
//handle changes to data
const changeHandler = (e) => {
const { name, value } = e.target;
setState((state) => ({
...state,
[name]: value
}));
};
//update record on submit
const submitHandler = (e) => {
e.preventDefault();
const { make, model, year, price, isSold } = state;
axios
.post("http://localhost:5000/vehicles/editVehicle/" + id, {
make,
model,
year,
price,
isSold
})
.then((res) => {
console.log(res);
navigate("/");
})
.catch(console.log);
};
return (
<div className="editVehicle">
<form className="editVehicle_form" onSubmit={submitHandler}>
<Link to="/" className="back_btn">
Back
</Link>
<h1>Update Vehicle Details</h1>
<p>Please fill out all fields</p>
<input
name="make"
placeholder="Make"
type="text"
value={state.make}
onChange={changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="model"
placeholder="Model"
type="text"
value={state.model}
onChange={changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="year"
placeholder="Year"
type="text"
value={state.year}
onChange={changeHandler}
className="editVehicle_form_input"
/>
<br />
<input
name="price"
placeholder="Price"
type="text"
value={state.price}
onChange={changeHandler}
className="editVehicle_form_input"
/>
<br />
<label className="addVehicle_form_radio_label">
Available
<input
name="isSold"
type="radio"
value={false}
onChange={changeHandler}
className="editVehicle_form_radio"
/>
</label>
<label className="editVehicle_form_radio_label">
Sold
<input
name="isSold"
type="radio"
value={true}
onChange={changeHandler}
className="editVehicle_form_radio"
/>
</label>
<br />
<input type="submit" value="Save" className="editVehicle_submit" />
</form>
</div>
);
};
can't find way how to resolve this problem.
Errors in browser:
Uncaught Error: Invalid hook call. Hooks can only be called inside
of the body of a function component. This could happen for one of
the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to
debug and fix this problem.
The above error occurred in the component:
Provider#http://localhost:3000/static/js/bundle.js:49534:15
Consider adding an error boundary to your tree to customize error
handling behavior. Visit https://reactjs.org/link/error-boundaries
to learn more about error boundaries.
INDEX.JS
import React from 'react';
import ReactDOM from 'react-dom';
import Router from './Router';
import { createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import { Provider } from 'react-redux'
import rootReducer from './Redux/Reducers/index.js'
const store = createStore( rootReducer, composeWithDevTools() )
ReactDOM.render(
<Provider store={ store }>
<Router />
</Provider >,
document.getElementById( 'root' ) );
Reducers/index.js
import loginPageReducer from './LoginPage.js'
import { combineReducers } from 'redux'
const rootReducer = combineReducers( {
loginPageReducer
} )
export default rootReducer
Reducers/LoginPage.js
const INIT_STATE = {
view: 'login',
msg: '',
loader: false,
}
const loginPageReducer = ( state = INIT_STATE, action ) =>
{
switch ( action.type )
{
case "LOADER_OFF":
return state.loader = false
case "LOADER_ON":
return state.loader = true
case "MSG_SET":
return state.msg = action.msg
case "MSG_CLEAR":
return state.msg = ''
case "VIEW_CHANGE":
return state.view = action.view
default:
return state;
}
}
export default loginPageReducer
loginPage component
import React, { useState } from 'react'
import '../Styles/loginPage.scss'
import axios from 'axios'
import { useDispatch, useSelector } from 'react-redux'
import loginPageActions from '../Redux/actions/LoginPage'
export default function LoginPage ()
{
const { msg_clear, msg_set, loader_off, loader_on, view_change } = loginPageActions
const msg = useSelector( state => state.LoginPageReducer.msg )
const view = useSelector( state => state.LoginPageReducer.view )
const loader = useSelector( state => state.LoginPageReducer.loader )
const dispatch = useDispatch()
const [inputs, setInputs] = useState( {
username: '',
password: '',
password2: '',
email: ''
} )
const handleInputs = function ( e )
{
const { name, value } = e.target
setInputs( { ...inputs, [name]: value } )
}
const handleSubmit = async ( e ) =>
{
try
{
e.preventDefault();
dispatch( msg_clear() )
dispatch( loader_on() )
if ( view === login)
{
// logowanie
const query = await axios( {
method: 'post',
url: '/api/users/login',
data: {
username: inputs.username,
password: inputs.password
}
} )
const token = query.data.token
localStorage.setItem( "token", token );
return window.location.href = "/kalkulator"
}
else
{
//rejestracja
const query = await axios( {
method: 'post',
url: '/api/users/register',
data: {
username: inputs.username,
password: inputs.password,
password2: inputs.password2,
email: inputs.email
}
} )
if ( query.status === 200 )
{
dispatch( msg_set( 'Zarejestrowano, możesz się zalogować' ) )
dispatch( view_change( true ) )
}
}
}
catch ( err )
{
if ( err ) return dispatch( msg_set( err.response.data.msg ) )
}
finally
{
dispatch( loader_off() )
}
}
/////////////
/// Renderowanie widoku
/////////////
return (
<main>
<div id="MainContainerStyle">
<span id="thatWhitePartOnBottom"></span>
<header>
<h1 id="HeaderH1" >Kalkulator mas</h1>
</header>
<button className="Buttons" onClick={ () => dispatch( view_change( !view ) ) }>
{ view ?
`Already have account? Click to log in!`
:
`Doesn't have account? Click me if you want to register new one` }
</button>
<form onSubmit={ handleSubmit } id="Form">
<input type="text"
value={ inputs.username }
placeholder={ view ? 'username' : 'Login or E-mail' }
name="username" required onChange={ handleInputs }
/>
{ view ?
<input type="email"
placeholder="email"
name="email"
value={ inputs.email }
required
onChange={ handleInputs } />
:
null
}
<input type="password"
value={ inputs.password }
placeholder="Password:"
name="password"
required
onChange={ handleInputs }
/>
{ view ?
<input type="password"
value={ inputs.password2 }
placeholder="Password again:"
name="password2"
required
onChange={ handleInputs } />
:
null
}
<input type="submit" className="Buttons" />
{ loader ? <span className="loader"></span> : null }
{ msg !== '' ? <p className="msg">{ msg }</p> : null }
</form>
</div>
</main>
)
}
Router
import { BrowserRouter, Routes, Route } from "react-router-dom";
import './Styles/global.scss'
import LoginPage from "./Pages/LoginPage";
import Kalkulator from "./Pages/Kalkulator";
function App ()
{
return (
<>
<BrowserRouter>
<Routes>
<Route path="/" element={ <LoginPage /> } />
<Route path="/kalkulator" element={ <Kalkulator /> } />
</Routes>
</BrowserRouter>
</>
)
}
export default App;
might be this problem: https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
Assuming myapp and mylib are sibling folders, one possible fix is to run npm link ../myapp/node_modules/react from mylib. This should make the library use the application’s React copy.
..or maybe "react-redux" is not installed, check package.json
Trying my hands at ReactJS fetch() examples. As mentioned this.props.history.push() not working, it is not giving an error, but it is simply not redirecting. Tried to read other answers to this question on StackOverflow, but many of them are either too complex(some ppl showing off) or some not very clear.
index.js:
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import { BrowserRouter as Router, NavLink, Switch, Route, useHistory } from "react-router-dom";
import reportWebVitals from "./reportWebVitals";
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById("root")
);
App.js :
import "./App.css";
import React from "react";
import { BrowserRouter as Router, NavLink, Switch, Route, useHistory } from "react-router-dom";
import RouterPage1 from "./RouterPage1";
import RouterPage2 from "./RouterPage2";
export default function App(props) {
let history = useHistory();
return (
<div>
<nav>
<ol>
<li>
<NavLink to="/RouterPage1">RouterPage1</NavLink>
</li>
<li>
<NavLink to="/RouterPage2">RouterPage2</NavLink>
</li>
<li>
<NavLink to="/RouterPageBoth">RouterPageBoth</NavLink>
</li>
</ol>
</nav>
<Switch>
<Route exact path="/RouterPage1">
<RouterPage1 history={history} />
</Route>
<Route exact path="/RouterPage2">
<RouterPage2 history={history} />
</Route>
</Switch>
</div>
);
}
RouterPage2.js(only the necessary code pasted, not the entire component for brevity):
addastakeholder = () => {
let newstakeholder = JSON.stringify(this.state.newstakeholder);
fetch("http://localhost:8080/OneToOneMappingPractice/add", {
method: "POST",
headers: { "Content-type": "application/json" },
body: newstakeholder,
}).then((r) => {
if (r.ok) {
//window.location.href = "/RouterPage2";
this.setState({ newstakeholder: { name: "", address: { house_number: "", streetName: "" } } });
this.props.history.push("/RouterPage2");
}
});
};
when I use the addastakeholder(), it is POSTing successfully, data is being entered in the DB, but it is not giving me an error and not redirecting. In the App.js, if I use the props and not useHistory(), it gives me "this.props.history not defined" error, even though I have enclosed App component in BrowserRouter component in the index.js.
Why is it so?
Secondly, if I use the commented out window.location.href = "/RouterPage2", it works(POSTing is successfull), but I am not able to see POST log in Development Tools:Network tab(Firefox). Why is this so?
Tried this.context.history.push("/RouterPage2"), does not work, same undefined error.
P.S.:edit 1:
the full RouterPage2.js(Kindly ignore result variable and the related code. Consider only result2.):
import React from "react";
export default class RouterPage2 extends React.Component {
constructor(props) {
super(props);
this.state = {
stakeholders: [],
errorString: "",
newstakeholder: { name: "", address: { house_number: "", streetName: "" } },
};
}
componentDidMount() {
fetch("http://localhost:8080/OneToOneMappingPractice/getAll")
.catch((error) => this.setState({ errorString: error }))
.then((result) => result.json())
.then((result) => this.setState({ stakeholders: result }));
}
addastakeholder = () => {
let newstakeholder = JSON.stringify(this.state.newstakeholder);
fetch("http://localhost:8080/OneToOneMappingPractice/add", {
method: "POST",
headers: { "Content-type": "application/json" },
body: newstakeholder,
}).then((r) => {
if (r.ok) {
//window.location.href = "/RouterPage2";
this.setState({ newstakeholder: { name: "", address: { house_number: "", streetName: "" } } });
this.props.history.push("/RouterPage2");
}
});
};
render() {
let result, result2;
let error = false;
if (this.state.stakeholders.length > 0)
result = (
<ol>
{this.state.stakeholders.map((stakeholder) => (
<li key={stakeholder.stakeholder_id}>
{stakeholder.stakeholder_name} | {stakeholder.stakeholder_type} |
{stakeholder.stakeholder_email_id} | {stakeholder.stakeholder_contactno} |
{stakeholder.stakeholder_bankname} | {stakeholder.stakeholder_bankBranch} |
{stakeholder.stakeholder_IFSC} | {stakeholder.stakeholder_AccNo} |
{stakeholder.stakeholder_AccType} | {stakeholder.stakeholder_PAN}
</li>
))}
</ol>
);
else result = false;
if (this.state.stakeholders.length > 0)
result2 = (
<ol>
{this.state.stakeholders.map((stakeholder) => (
<li key={stakeholder.id}>
{stakeholder.name}|{stakeholder.address.house_number}|{stakeholder.address.streetName}
</li>
))}
</ol>
);
else result2 = false;
if (this.state.errorString !== "undefined") error = this.state.errorString;
let blank = false;
if (result == false) blank = <h5>There are no records to display.</h5>;
return (
<div>
<h1>Stakeholder details :</h1>
{result2}
{error}
{blank}
<form>
Name :{" "}
<input
type="text"
placeholder="Name"
value={this.state.newstakeholder.name}
onChange={(e) => {
this.setState({ newstakeholder: { ...this.state.newstakeholder, name: e.target.value } });
}}
/>
<br></br>
StreetName :{" "}
<input
type="text"
placeholder="StreetName"
value={this.state.newstakeholder.address.streetName}
onChange={(e) => {
this.setState({
newstakeholder: {
...this.state.newstakeholder,
address: { ...this.state.newstakeholder.address, streetName: e.target.value },
},
});
}}
/>
<br></br>
HouseNumber :{" "}
<input
type="text"
placeholder="HouseNumber(Digits Only)"
value={this.state.newstakeholder.address.house_number}
onChange={(e) => {
this.setState({
newstakeholder: {
...this.state.newstakeholder,
address: { ...this.state.newstakeholder.address, house_number: e.target.value },
},
});
}}
/>
<br></br>
<button type="button" onClick={this.addastakeholder}>
Add Stakeholder
</button>
</form>
</div>
);
}
}
Tried everything. As suggested by Kurtis above in the comments, for troubleshooting purposes, did : console.log(this.props);
Got following response :
as you can see, there is the push function with different signature, hence tried : this.props.history.push("/RouterPage2", ""). Again did not work.
Hence, thought of trying the go(). And it worked.
this.props.history.go("/RouterPage2");
working now perfectly.
After submitting my form I am not getting the submitted data on console and also the page is not routing
I am not getting the reason behind this. Searching for 2 days but still not got a suitable answer. Can anyone tell me the solution?
import axios from "axios";
import { BrowserRouter as Router, Link, Route, Switch } from "react-router-dom";
// import { createBrowserHistory as history } from "history";
import { withRouter } from "react-router-dom";
import DoneStatus from "./DoneStatus";
class Body extends React.Component {
titleDescMap = new Map();
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChangeTitle = this.handleChangeTitle.bind(this);
this.handleChangeDescription = this.handleChangeDescription.bind(this);
this.handleCheckBoxChange = this.handleCheckBoxChange.bind(this);
}
state = {
countTodo: 1,
valueTitle: "",
valueDescription: "",
checkStatus: false,
routing: false,
};
statesStatus() {
return {
checkStatus: this.state.checkStatus,
};
}
handleChangeTitle(event) {
this.setState({
valueTitle: event.target.value,
});
}
handleChangeDescription(event) {
this.setState({
valueDescription: event.target.value,
});
}
handleCheckBoxChange(event) {
this.setState((prev) => ({ checkStatus: !prev.checkStatus }));
console.log(this.state.checkStatus);
}
handleSubmit(event) {
// Debugging my states
console.log("Id: " + this.state.id);
console.log("Title: " + this.state.valueTitle);
console.log("Description: " + this.state.valueDescription);
console.log("Check Status: " + this.state.checkStatus);
event.preventDefault();
var previousTitle = this.titleDescMap.has(this.state.valueTitle);
// Sending data to database
// Checking if any title and desc is previously stored
if (previousTitle) {
alert("Please Enter Another Title (which you have never used)");
} else {
// Setting the values in title and description into Map
this.titleDescMap.set(this.state.valueTitle, this.state.valueDescription);
console.log(this.titleDescMap);
// Updating id as counter increases 1
this.setState((previousState) => ({
countTodo: previousState.countTodo + 1,
}));
if (this.state.checkStatus) {
const backendData = {
countTodo: this.state.countTodo,
title: this.state.valueTitle,
description: this.state.valueDescription,
};
axios
.post("https://todo-list-site.herokuapp.com/todo-data", backendData)
.then((data) => {
console.log(data);
this.props.history.push("/submit");
})
.catch((err) => {
console.error("Error");
});
console.log(backendData);
}
}
}
render() {
console.log(this.state.checkStatus);
return (
<div className="body-container">
<p className="body-direction">Fill To Save Your Todo</p>
<form method="post" onSubmit={this.handleSubmit}>
<div className="form-group">
<label>Title</label>
<input
type="text"
className="form-control"
placeholder="Title here"
value={this.state.valueTitle}
onChange={this.handleChangeTitle}
/>
</div>
<div className="form-group">
<label>Description</label>
<br />
<textarea
className="form-control"
placeholder="Description here"
rows="4"
cols="40"
value={this.state.valueDescription}
onChange={this.handleChangeDescription}
/>
</div>
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
onChange={this.handleCheckBoxChange}
/>
<label className="form-check-label body-input-label">
Save Permanently
</label>
</div>
<button
type="submit"
// onClick={() => history().push("/submit")}
className="btn btn-primary"
>
+ Add
</button>
</form>
</div>
);
}
}
export default withRouter(Body);
I have updated my code as per the given solution on this question. But still not getting the proper output
I want to send all the data in the form into my backend and render it on another page.
Data is submitting but I am not getting it on the console. Also routing is the major issue here.
I have added the file which includes all the routes
import Header from "./Header";
import Body from "./Body";
import DoneStatus from "./DoneStatus";
import Saved from "./Saved";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
// import Footer from "./Footer";
class App extends React.Component {
render() {
const body = new Body();
const checkStatus = body.statesStatus();
return (
<React.Fragment>
<Router>
<Header />
<Switch>
<Route
exact
path="/"
render={() => {
return (
<div className="app-container">
<Body />
</div>
);
}}
></Route>
</Switch>
<Switch>
<Route
exact
path="/saved"
render={() => {
return <Saved />;
}}
></Route>
</Switch>
{/* <Footer /> */}
<Switch>
<Route
exact
path="/submit"
render={() => {
return <DoneStatus checkedStatus={checkStatus.checkStatus} />;
}}
></Route>
</Switch>
</Router>
</React.Fragment>
);
}
}
export default App;
You are not waiting for your POST to finish, and as #Drew Reese points, you are calling the history wrong
handleSubmit(event) {
// Debugging my states
console.log("Id: " + this.state.id);
console.log("Title: " + this.state.valueTitle);
console.log("Description: " + this.state.valueDescription);
console.log("Check Status: " + this.state.checkStatus);
event.preventDefault();
var previousTitle = this.titleDescMap.has(this.state.valueTitle);
// Sending data to database
// Checking if any title and desc is previously stored
if (previousTitle) {
alert("Please Enter Another Title (which you have never used)");
} else {
// Setting the values in title and description into Map
this.titleDescMap.set(this.state.valueTitle, this.state.valueDescription);
console.log(this.titleDescMap);
// Updating id as counter increases 1
this.setState((previousState) => ({
countTodo: previousState.countTodo + 1,
}));
if (this.state.checkStatus) {
const backendData = {
countTodo: this.state.countTodo,
title: this.state.valueTitle,
description: this.state.valueDescription,
};
axios.post(
"https://todo-list-site.herokuapp.com/todo-data",
backendData
).then((response) => {
console.log(response);
history.push("/submit");
}).catch((error) => {
console.error(error);
});
}
}
}
Also, you are not waiting for the countTodo state to be setted after getting it to send it to the backend, that might get you unexpected behaviours some times
I think you are missing handling promise, please find below solution:
axios.get(`https://todo-list-site.herokuapp.com/todo-data`)
.then(backendData => {
console.log(backendData);
})
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.