I am creating a React app which can be used to manage company events. There are two components related to events that aren't working at the moment. These are the edit event component, and the event card component which displays all the information relevant to the event. I'm trying to pass the event ID in order to identify the relevant event to be edited or viewed. The useParams() hook is used to pass the ID. When I set up a route for the edit event feature and view event card feature, I get the following errors in the console.
The error shown in the edit event route is,
No routes matched location "/editEvent/(event ID)".
The error shown in the event card route is,
No routes matched location "/event/(event ID)"
The (event ID) contains the ID of the event that I'm trying to edit or view. The correct ID was visible in the address of the route.
I have attached the code of all components related to the edit event and event card features.
src/App.js
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import AddProject from './Components/AddProject';
import AllProjects from './Components/AllProjects';
import AddEvents from './Components/AddEvents';
import AllEvents from './Components/AllEvents';
import EditProject from './Components/EditProject';
import ProjectDetails from './Components/ProjectDetails';
import EventCard from './Components/EventCard';
import EditEvent from './Components/EditEvent';
import { NoMatch } from './Components/NoMatch';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<AddProject />} />
<Route path="/allProjects" element={<AllProjects />} />
<Route path="/addEvents/:projectName" element={<AddEvents />} />
<Route path="/allEvents/:projectName" element={<AllEvents />} />
<Route path="/editProject/:id" element={<EditProject />} />
<Route Path="/project/:id" element={<ProjectDetails />} />
<Route Path="/event/:id" element={<EventCard />} />
<Route Path="/editEvent/:id" element={<EditEvent/>} />
<Route Path='*' element={<NoMatch/>}></Route>
</Routes>
</Router>
);
}
export default App;
src/Components/AllEvents.js
import { React, useState, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { Button, Card } from 'react-bootstrap';
import axios from "axios";
function AllEvents() {
const [listOfEvents, setListOfEvents] = useState([]);
useEffect(() => {
axios.get("/getEvent").then((response) => {
setListOfEvents(response.data);
})
}, []);
const { projectName } = useParams();
const handleDelete = (_id) => {
axios.delete(`/deleteEvent/${_id}`)
.then((res) => {
console.log(res);
console.log(res.data);
})
const newList = listOfEvents.filter((event) => event._id !== _id);
alert("Event was deleted");
setListOfEvents(newList);
}
let navigate = useNavigate();
const filteredList = listOfEvents.filter((event) => event.projectName === projectName);
return (
<div id="allEvents">
<h1 style={{ textAlign: "center" }}>{projectName}</h1>
<h3>All Events</h3>
{filteredList.length > 0 ? (filteredList.map((events) => {
return (
<div>
<Card className="detailsCard" border="dark">
<div className="details">
<span className="title">Event Name:</span>
<span className="data">{events.eventName}</span>
</div>
<div className="details">
<span className="title">Event Description:</span>
<span className="data">{events.eventDescription}</span>
</div>
<div className="details">
<span className="title">Event Start Date:</span>
<span className="data">{events.eventStartDate}</span>
</div>
<div className="details">
<span className="title">Event End Date:</span>
<span className="data">{events.eventEndDate}</span>
</div>
<div>
<Button variant="success" size="sm" type="submit" onClick={() => { navigate(`/event/${events._id}`) }}>View Event Card</Button>
<Button className="eventButton" variant="warning" size="sm" type="submit" onClick={() => { navigate(`/editEvent/${events._id}`) }}>Edit Event</Button>
<Button className="eventButton" variant="danger" size="sm" type="submit" onClick={() => { handleDelete(events._id) }}>Delete Event</Button>
</div>
</Card>
</div>
);
})
) : (
<div>
<p>No events have been added yet</p>
</div>
)}
<br />
<Button variant="secondary" size="lg" onClick={() => { navigate(`/addEvents/${projectName}`) }}>Add new event</Button>
</div>
);
}
export default AllEvents;
src/Components/EditEvent.js
import { React, useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Form, Card, Button,CloseButton } from 'react-bootstrap';
import axios from "axios";
function EditEvent() {
const [projectName, setProjectName] = useState();
const [eventName, setEventName] = useState();
const [eventDescription, setEventDescription] = useState();
const [eventStartDate, setEventStartDate] = useState();
const [eventEndDate, setEventEndDate] = useState();
const { id } = useParams();
let navigate = useNavigate();
const editEvent = () => {
axios.put(`/updateEvent/${id}`, {
eventName,
eventDescription,
eventStartDate,
eventEndDate
}).then((res) => {
alert("Project has been edited");
console.log("Project edited");
});
}
useEffect(() => {
axios.get(`/getEvent/${id}`).then((res) => {
setProjectName(res.data.events.projectName);
setEventName(res.data.events.eventName);
setEventDescription(res.data.events.eventDescription);
setEventStartDate(res.data.events.eventStartDate);
setEventEndDate(res.data.events.setEventEndDate);
console.log(res.data.events);
});
// eslint-disable-next-line
}, []);
return (
<div>
<div className="eventCard">
<Card border="dark" >
<Card.Header>
<div className="eventCardHeader">
Edit an Event
<CloseButton className="closeButton" onClick={() => { navigate(`/allEvents/${projectName}`) }} />
</div>
</Card.Header>
<Card.Body>
<Form>
<Form.Group>
<h5>Edit Event Name</h5>
<Form.Control as="textarea"
rows={1}
placeholder='Add Event Name'
value={eventName}
onChange={(event) => { setEventName(event.target.value) }}>
</Form.Control><br />
</Form.Group>
<Form.Group>
<h5>Edit Event Description</h5>
<Form.Control as="textarea"
rows={3}
placeholder='Add Event Description'
value={eventDescription}
onChange={(event) => { setEventDescription(event.target.value) }}>
</Form.Control><br />
</Form.Group>
<h5>Edit Event Duration</h5>
<Form.Label>Start Date</Form.Label><br />
<input
type="date"
min={new Date().toISOString().split('T')[0]}
max="2030-12-31"
value={eventStartDate}
onChange={(event) => { setEventStartDate(event.target.value) }} /><br />
<Form.Label>End Date</Form.Label><br />
<input
type="date"
min={new Date().toISOString().split('T')[0]}
max="2030-12-31"
value={eventEndDate}
onChange={(event) => { setEventEndDate(event.target.value) }} /><br />
</Form>
<Card.Footer style={{ paddingLeft: '50%' }}>
<Button variant="warning" size="lg" type="submit" onClick={editEvent}>Edit Project</Button>
</Card.Footer>
</Card.Body>
</Card>
</div>
</div>
);
}
export default EditEvent;
src/Components/EventCard.js
import { React, useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";
import axios from "axios";
import { CloseButton } from 'react-bootstrap';
function EventCard(){
const [eventName,setEventName] = useState();
const [eventDescription,setEventDescription] = useState();
const [eventStartDate,setEventStartDate] = useState();
const [eventEndDate,setEventEndDate] = useState();
const { id } = useParams();
let navigate = useNavigate();
useEffect(() =>{
axios.get(`/getEvent/${id}`).then((res) => {
console.log("Hello");
setEventName(res.data.event.eventName);
setEventDescription(res.data.event.eventDescription);
setEventStartDate(res.data.event.eventStartDate);
setEventEndDate(res.data.event.eventEndDate);
console.log("EventData",res.data.event);
});
// eslint-disable-next-line
},[]);
return(
<div>
<CloseButton className="closeButton" onClick={() => { navigate("/allProjects") }} />
{eventName}
{eventDescription}
{eventStartDate}
{eventEndDate}
</div>
);
}
export default EventCard;
routes/events.js
const express = require('express');
const router = express.Router();
const eventModel = require('../models/Events');
// Add an event
router.post("/createEvent", async (req, res) => {
const event = req.body;
const newEvent = new eventModel(event);
await newEvent.save();
res.json(event);
});
// Retrieve all events
router.get("/getEvent", (req, res) => {
eventModel.find({}, (err, result) => {
if (err) {
res.json(err);
} else {
res.json(result);
}
});
});
// Retrieve a specific event
router.get("/getEvent/:id", (req,res) => {
let eventId = req.params.id;
eventModel.findById(eventId,(err,event) => {
if(err){
return res.status(400).json({success:false, err});
}
return res.status(200).json({
success:true,
event
});
});
});
// Update an event
router.put('/updateEvent/:id',(req,res) => {
eventModel.findByIdAndUpdate(
req.params.id,
{
$set:req.body
},
(err,updatedEvent) => {
if(err){
return res.status(400).json({error:err});
}
return res.status(200).json({
success:"Updated succesfully"
});
}
);
});
// Delete an event
router.delete('/deleteEvent/:id',(req,res) => {
eventModel.findByIdAndRemove(req.params.id).exec((err,deletedEvent) => {
if(err) return res.status(400).json({
message:"Delete unsuccessful",err
});
return res.json({
message:"Delete successful",deletedEvent
});
});
});
module.exports = router;
Server.js
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const cors = require('cors');
const projectRoutes = require('./routes/projects');
const eventRoutes = require('./routes/events');
app.use(express.json());
app.use(cors());
app.use(projectRoutes);
app.use(eventRoutes);
app.get("/", (req, res) => {
res.send("Hello world");
}
);
//Actual url was removed when posting to stackoverflow
const DB_URL = '';
mongoose
.connect(DB_URL)
.then(() => {
console.log('MongoDB connected');
})
.catch((err) => console.log('DB connection error',err));
app.listen(5000, () => console.log("Server is running in port 5000"));
I appreciate any help that I can get.
Related
this is my dashboard page , i should be directed to it after the login , and i am sure that the login process is successful , but after the login I face a plank page .
import React from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import "./Chat.css"
const DashboardPage = (props) => {
const nameRef = React.createRef();
const [chatrooms, setChatrooms] = React.useState([]);
const chatname = nameRef.current.value;
const createChat = (e) => {
e.preventDefault()
axios
.post("http://localhost:5000/chatroom", {
name:chatname })
.then((response) => {
console.log(response.data.message)
})
.catch((err) => {
console.log(err);
});
};
const getChatrooms = () => {
axios
.get("http://localhost:5000/chatroom", {
headers: {
Authorization: "Bearer " + localStorage.getItem("CC_Token"),
},
})
.then((response) => {
setChatrooms(response.data);
console.log(response.data)
})
.catch((err) => {
setTimeout(getChatrooms, 3000);
});
};
React.useEffect(() => {
getChatrooms();
// eslint-disable-next-line
}, []);
return (
<div className="card">
<div className="cardHeader">Chatrooms</div>
<div className="cardBody">
<div className="inputGroup">
<label htmlFor="chatroomName">Chatroom Name</label>
<input
type="text"
name="chatroomName"
id="chatroomName"
placeholder="ChatterBox Nepal"
ref={nameRef}
/>
</div>
</div>
<button onClick={createChat} type="button">Create Chatroom</button>
<div className="chatrooms">
{chatrooms.map((chatroom) => (
<div key={chatroom._id} className="chatroom">
<div>{chatroom.name}</div>
<Link to={"/chat/" + chatroom._id}>
<div className="join">Join</div>
</Link>
</div>
))}
</div>
</div>
);
};
export default DashboardPage;
and this is the App.js :
import './App.css';
import Navigation from './components/Navigation';
import {BrowserRouter,Routes,Route} from "react-router-dom"
import Home from "./pages/Home"
import Login from "./pages/Login"
import Signup from "./pages/Signup"
import Chat from "./pages/Chat"
import 'font-awesome/css/font-awesome.min.css';
import io from "socket.io-client";
import makeToast from "./Toaster";
import React from "react";
import DashboardPage from './pages/DashboardPage';
function App() {
const [socket, setSocket] = React.useState(null);
const setupSocket = () => {
const token = localStorage.getItem("CC_Token");
if (token && !socket) {
const newSocket = io("http://localhost:5000", {
query: {
token: localStorage.getItem("CC_Token"),
},
});
newSocket.on("disconnect", () => {
setSocket(null);
setTimeout(setupSocket, 3000);
makeToast("error", "Socket Disconnected!");
});
newSocket.on("connect", () => {
makeToast("success", "Socket Connected!");
});
setSocket(newSocket);
}
};
React.useEffect(() => {
setupSocket();
//eslint-disable-next-line
}, []);
return (
<BrowserRouter>
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login setupSocket={setupSocket} />} />
<Route path="/signup" element={<Signup />} />
<Route path="/dashboard" element={<DashboardPage socket={socket} />} />
<Route path="/chat/:id" element={<Chat socket={socket} />} />
</Routes>
</BrowserRouter>
);
}
export default App;
and this is the chat page :
import React from "react";
import "./Chat.css"
const Chat = ({ match, socket }) => {
const chatroomId = match.params.id;
const [messages, setMessages] = React.useState([]);
const messageRef = React.useRef();
const [userId, setUserId] = React.useState("");
const sendMessage = () => {
if (socket) {
socket.emit("chatroomMessage", {
chatroomId,
message: messageRef.current.value,
});
messageRef.current.value = "";
}
};
React.useEffect(() => {
const token = localStorage.getItem("CC_Token");
if (token) {
const payload = JSON.parse(atob(token.split(".")[1]));
setUserId(payload.id);
}
if (socket) {
socket.on("newMessage", (message) => {
const newMessages = [...messages, message];
setMessages(newMessages);
});
}
//eslint-disable-next-line
}, [messages]);
React.useEffect(() => {
if (socket) {
socket.emit("joinRoom", {
chatroomId,
});
}
return () => {
//Component Unmount
if (socket) {
socket.emit("leaveRoom", {
chatroomId,
});
}
};
//eslint-disable-next-line
}, []);
return (
<div className="chatroomPage">
<div className="chatroomSection">
<div className="cardHeader">Chatroom Name</div>
<div className="chatroomContent">
{messages.map((message, i) => (
<div key={i} className="message">
<span
className={
userId === message.userId ? "ownMessage" : "otherMessage"
}
>
{message.name}:
</span>{" "}
{message.message}
</div>
))}
</div>
<div className="chatroomActions">
<div>
<input
type="text"
name="message"
placeholder="Say something!"
ref={messageRef}
/>
</div>
<div>
<button className="join" onClick={sendMessage}>
Send
</button>
</div>
</div>
</div>
</div>
);
};
export default Chat;
so as i said above , what should i do ??
before i edit it a liitle bit , it showed only the create room part of the dashboard page , but not the ( join room ) part .
now it does not show anything , and I am lost !!!!!!!!!!!!!!
I just started learning React and I have a question about my app. It is about the onSubmit function located in the formic. The point is that when I open the application on the local server, I go to the http: // localhost: 3001 / employees route, the onSubmit function works and displays values to me. But when I open it on node.js, after clicking the button, it becomes inactive and nothing happens. Same onClick function shows me nothing.
App.jsx
import "./App.css";
import EditEmployee from "./EditEmployee";
import EmployeeList from "./InternList";
import { Routes, Route } from "react-router-dom";
function App() {
return (
<div className="App">
<Routes>
<Route path="/employees/:id" element={<EditEmployee/>} />
<Route path="/" element={<EmployeeList />} />
</Routes>
</div>
);
}
export default App;
EditEmployee.jsx
import React, {useState } from 'react';
import { useParams } from 'react-router';
import { NavLink } from 'react-router-dom';
import { Formik } from 'formik';
const EditEmployee = () => {
const { id } = useParams();
const [Employee, setEmployee] = useState(0);
const fetchEmployee = async () => {
const response = await fetch(`http://localhost:3001/employees/${id}`);
const Employee = await response.json();
setEmployee(Employee)
}
fetchEmployee();
return (
<div>
<NavLink to="/">Back to list </NavLink>
<Formik
validateOnhange={false}
validateOnBlur={false}
initialValues={{ id: id, name: '', email: ''}}
validate={values => {
const errors = {};
if (!values.name)
{
errors.name = <a>Required name</a>
}
if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email))
{
errors.email = <a>Invalid email address</a>
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
{errors.name}
<input
type="text"
name="name"
onChange={handleChange}
onBlur={handleBlur}
value={values.name}
/>
{errors.email}
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
<button type="submit" disabled={isSubmitting}
onClick={() => { alert("Saving reports in demo mode is not
available")}}>Submit</button>
</form>
)}
</Formik>
</div>
);
};
export default EditEmployee;
server.js
const express = require('express');
const path = require('path');
const app = express();
const bodyparser = require('body-parser');
app.use(bodyparser.json());
app.use(express.static (path.join(__dirname, 'build')));
app.get('*', function(req, res){
res.sendFile(path.join(__dirname, 'build', 'index.html'));
})
app.listen(3000);
the button is Inactive becuase you make it inactive here
<button type="submit" disabled={isSubmitting}
onClick={() => { alert("Saving reports in demo mode is not
available")}}>Submit</button>
You might want to do this
<button type="submit" onClick={() => { alert("Saving reports in demo mode is not available")}}>Submit</button>
I'm trying to display an error message when a user tries to sign in with an unregistered user but I'm not able to get that error message on the frontend(reactjs) that I am sending from my backend(nodejs, express, MongoDB).
I am using redux to handle the state of the react app.
user login form onSubmit code:
const onSubmit = (data) => {
if (isLogin) {
dispatch(signin(data, history));
} else {
dispatch(signup(data, history));
}
};
actions creators for auth
import * as api from "../api";
export const signin = (formData, history) => async (dispatch) => {
try {
// login the user
const { data } = await api.signIn(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
dispatch({ type: "ERROR", data: error.response.data.message });
}
};
export const signup = (formData, history) => async (dispatch) => {
try {
// sign up the user
const { data } = await api.signUp(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
}
};
reducers for auth:
const authReducer = (state = { authData: null }, action) => {
switch (action.type) {
case "AUTH":
localStorage.setItem("profile", JSON.stringify({ ...action?.data }));
return { state, authData: action?.data };
case "LOGOUT":
localStorage.clear();
return { state, authData: null };
case "ERROR":
return { state, authData: action?.data };
default:
return state;
}
};
export default authReducer;
Backend sign in code
const signin = async (req, res) => {
const { email, password } = req.body;
try {
const existingUser = await User.findOne({ email });
if (!existingUser)
return res.status(404).json({ message: "User doesn't exist." });
const isPasswordCorrect = await bcrypt.compare(
password,
existingUser.password
);
if (!isPasswordCorrect)
res.status(404).json({ message: "Invalid Credentials" });
const token = jwt.sign(
{ email: existingUser.email, id: existingUser._id },
"test",
{ expiresIn: "1h" }
);
res.status(200).json({ result: existingUser, token });
} catch (error) {
res.status(500).json({ message: "Something went wrong" });
}
};
sign API
import axios from "axios";
const API = axios.create({
baseURL: process.env.REACT_APP_BASE_URL,
});
export const signIn = (formData) => API.post("/user/signin", formData);
export const signUp = (formData) => API.post("/user/signup", formData);
Anyone, please help me with this.
Screenshots of the error response in Postman:
I just debugged the issue. First install redux-devtools-extension by npm install --save redux-devtools-extension
Then apply this in store(index.js file in your case) as follows
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import App from "./App";
import { reducers } from "./reducers";
import { composeWithDevTools } from "redux-devtools-extension";
const middleware = [thunk];
const store = createStore(
reducers,
composeWithDevTools(applyMiddleware(...middleware))
);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
And now you can use the error message anywhere as follows (your Auth.js file)
import React, { useState } from "react";
import { useSelector } from "react-redux";
import Input from "../utils/Input";
import Label from "../utils/Label";
import { useForm, FormProvider } from "react-hook-form";
import { GoogleLogin } from "react-google-login";
import { useDispatch } from "react-redux";
import { useHistory } from "react-router";
import { signin, signup } from "../../actions/auth";
const Auth = () => {
const [isLogin, setIsLogin] = useState(true);
const formMethods = useForm();
const auth = useSelector((state) => state.auth);
const { authData } = auth;
const { handleSubmit } = formMethods;
console.log(authData);
const dispatch = useDispatch();
const history = useHistory();
const changeScreen = () => {
setIsLogin(false);
dispatch({ type: "LOGOUT" });
};
const onSubmit = (data) => {
if (isLogin) {
dispatch(signin(data, history));
} else {
dispatch(signup(data, history));
}
};
const googleSuccess = async (res) => {
const result = res?.profileObj;
const token = res?.tokenId;
try {
dispatch({ type: "AUTH", data: { result, token } });
history.push("/");
} catch (error) {
console.log(error);
}
};
const googleFailure = (error) => {
console.log(error);
console.log("Google sign in was unsuccessful");
};
return (
<section className="col-start-1 col-end-2 md:col-start-2 md:col-end-3 row-start-2 row-end-3 md:row-start-1 md:row-end-2 mx-3 sm:mx-0 md:my-auto">
<div className=" w-full max-w-md bg-primaryOne px-6 py-8 rounded-md shadow-md mx-auto">
<FormProvider {...formMethods}>
<form className="" onSubmit={handleSubmit(onSubmit)}>
<div className="w-full flex justify-around mb-2">
<button
className={`${
isLogin
? "bg-secondaryTwo"
: "transition bg-transparent hover:bg-secondaryTwo"
} text-white text-xs font-bold px-6 py-4 rounded-full`}
type="button"
onClick={() => setIsLogin(true)}
>
LOG IN
</button>
<button
className={`${
!isLogin
? "bg-secondaryTwo"
: "transition bg-transparent hover:bg-secondaryTwo"
} text-white text-xs font-bold px-6 py-4 rounded-full`}
type="button"
onClick={() => changeScreen()}
>
SIGN UP
</button>
</div>
<div>
{!isLogin && (
<div>
<Label labelName="Name" />
<Input inputName="name" type="text" bgColor="primaryTwo" />
</div>
)}
<div>
<Label labelName="Email" />
<Input inputName="email" type="email" bgColor="primaryTwo" />
</div>
<div>
<Label labelName="Password" />
<Input
inputName="password"
type="password"
bgColor="primaryTwo"
/>
</div>
</div>
<div className="text-center">
<button
type="button"
onClick={() => setIsLogin(!isLogin)}
className="text-neutral font-extralight text-xs pt-6"
>
{authData && <h1 style={{ color: "red" }}>{authData}</h1>}
{!isLogin
? "Already have an account? Log In"
: "Don't have an account? Sign Up"}
</button>
</div>
<button className="bg-secondaryTwo hover:bg-secondaryOne transition px-4 py-3 w-full rounded-md text-white font-bold mt-4 shadow-md">
{isLogin ? "Log In" : "Sign Up"}
</button>
<div className="flex items-center py-6">
<div className="w-1/2 h-px bg-white bg-opacity-40"></div>
<p className="text-white px-1 text-xs">OR</p>
<div className="w-1/2 h-px bg-white bg-opacity-40"></div>
</div>
<div>
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_CLIENT_ID}
onSuccess={googleSuccess}
onFailure={googleFailure}
cookiePolicy="single_host_origin"
render={(renderProps) => (
<button
className="bg-blue-600 hover:bg-blue-500 transition px-4 py-3 w-full rounded-md text-white font-bold mb-4 shadow-md"
type="button"
onClick={renderProps.onClick}
disabled={renderProps.disabled}
>
<i className="fab fa-google mr-2"></i>Continue with Google
</button>
)}
/>
</div>
</form>
</FormProvider>
</div>
</section>
);
};
export default Auth;
And one last thing. Check nested object before using its properties like error.response.data.message (your auth.js actions file)
import * as api from "../api";
export const signin = (formData, history) => async (dispatch) => {
try {
// login the user
const { data } = await api.signIn(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log("An error occured while ");
const errMsg =
error.response && error.response.data.message
? error.response.data.message
: error.message;
dispatch({ type: "ERROR", data: errMsg });
console.log(errMsg);
}
};
export const signup = (formData, history) => async (dispatch) => {
try {
// sign up the user
const { data } = await api.signUp(formData);
dispatch({ type: "AUTH", data });
history.push("/");
} catch (error) {
console.log(error);
}
};
Hope it helps!
As far as I understood, everything is working fine, and actually, there is no error happening on the frontend side. You have to check the status code of "await api.signIn(formData);" response. If it is 200, it means that everything is ok otherwise you have to check the message in the response to get the message error. As on the frontend there is thrown error to be catched.
you can aslo use react-toastify . you can get status code and response message from error and store it in state object in reducers/auth.js and access it using useSelector() then create if else conditions according to status code and pass message to toast(#error_message#).
just see react-toastify and know how to use it.
I have a RESTful app built with React and Express Node, in it is a simple form with body and title inputs overlaid on a background image, when user clicks save, they are directed to another component with axios.get request displaying the their post.
My goal is to retrieve the data saved and display the image/posts in an array. Right now I am just testing the post retrieval, I will work on the images later. When testing the route in Postman, I am able to see all my posts using http://localhost:5000/getall, however when I use this path in my axios.get request I am seeing all the posts in a clutter, not separated: see example in image below. To access the arrays I us a <Card /> I import the a Card component (`) in my SharewallComp.js file.
How can I map this string array taken from mongo dB and show just one title/body per post?
I tried the following:
Retrieve data by id: let res = await axios.get(http://localhost:5000/getall${match.params.id}); but I get TypeError: Cannot read property 'params' of undefined.
I also tried the below with out match params and my result was just the numbers see error screenshot below:
<Card.Title className="text-center mt-5">
Title: {(title).map((t, index) => (
<Card.Text key={index} className="text-light"> {(t, index)} </Card.Text>
))}
Body: {(body).map((b, index) => (
<Card.Text key={index} className="text-light"> {(b, index)} </Card.Text>
))}
Here is my attempt: Mapping is not my strongest skill. Any help I appreciate so much!
import React, { useState, useEffect } from "react";
import axios from "axios";
import Cards from "./Cards";
const ShareWallComp = ({ match }) => {
const [url, setUrl] = useState([]);
const history = useHistory();
const loadimg = async () => {
try {
let res = await axios.get(
`http://localhost:5000/geturls/${(match.params.name="grace")}`
);
setUrl(res.data.map((d) => d.url));
} catch (error) {
console.log(error);
}
};
useEffect(() => {
// login code
loadimg();
}, []);
return (
<div className="getcross">
<Container className="mt-5 ml-auto mr-auto">
<div className="mt-4">
<Navi />
</div>
<h1 className="text-center">
ShareVerse
<span className="text-success"> Wall</span>
</h1>
<div>
<div className="shadow p-3 mb-5 bg-white rounded">
<Card className="bg-dark shadow text-white">
{url
.filter((name) => name.includes("grace"))
.map((urlData) => (
<Card.Img key={url.name} src={urlData} alt="Card image" />
))}
<Card.ImgOverlay>
<div className="text-center"><Cards /></div>
</Card.ImgOverlay>
</Card>
</div>
</div>
</Container>
</div>
);
};
export default ShareWallComp;
Here is the component where I have arrays for inputs
import React, { useState, useEffect } from "react";
import axios from "axios";
const ComponentName = (props) => {
const [body, setBody] = useState([]);
const [title, setTitle] = useState([]);
const loadData = async () => {
try {
// let res = await axios.get(
let res = await axios.get(`http://localhost:5000/getall`);
setTitle(res.data.map((t) => t.title));
setBody(res.data.map((b) => b.body));
} catch (error) {
console.log(error);
}
};
useEffect(() => {
loadData()
}, []);
return (
<div className="compoentclass">
<Container className="mt-5 ml-auto mr-auto">
<div className="text-center">
<Card.Title className="text-center mt-5">
Title: {(title).map((t) => (
<Card.Text className="text-light"> {(t)} </Card.Text>
))}
Body: {(body).map((b) => (
<Card.Text className="text-light"> {(b)} </Card.Text>
))}
</Card.Title>
</div>
</Container>
</div>
);
}
export default ComponentName;
example of posts clutered
error when retrieving data with id
the below screenshot an example of what I want my code to do:
The answer was to get all the data rather then mapping it : see the below corrected code, I hope this helps some one out there! So instead of setTitle(res.data.map((t) => t.title)); and setBody(res.data.map((t) => t.Body));, just get all the data: setPosts(res.data); Then call {post.body}
import React, { useState, useEffect } from "react";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import axios from "axios";
import "./css/sharewall.css";
const ComponentName = () => {
const [posts, setPosts] = useState([]);
const [comment, setComment] = useState("");
const [id, setId] = useState("");
const loadData = async () => {
try {
let res = await axios.get(`http://localhost:5000/getall`);
setPosts(res.data);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
loadData();
}, []);
return (
<div className="compoentclass">
<Container className="mt-5 ml-auto mr-auto">
<div className="text-center">
{posts.map((post, index) => (
<div>
<Card className="">
<Card.Img alt="" src={post.url} />
<Card.ImgOverlay className="overlay">
<Card.Title className="text-center mt-5">
<Card.Text className="cardStyle text-light">
{post.body}
</Card.Text>
</Card.Title>
</Card.ImgOverlay>
</Card>
{posts.map((post, index) => (
))}
</div>
</div>
))}
</div>
</Container>
</div>
);
};
export default ComponentName;
I've built an app that is running well when on the server generated from the npm start command, but when I set up a server with npm live-server, or a python simple HTTPserver, I'm getting this error when I navigate to the /login route.
Saying "Cannot GET /login". But at no point do I send a get request from what I can tell. When I navigate to the /login route, all that should appear is a form that takes in user info and sends a post request to get a token.
Here are all of my user Actions in my UserActions.js file. As you can see it's very minimal (I don't even have a /register, this is because I only have 1 admin user already in the database and have no need to register)
usrerActions.js
import {
SET_USER,
SET_ERRORS,
CLEAR_ERRORS,
LOADING_UI,
SET_UNAUTHENTICATED
} from "../types";
import axios from 'axios'
export const loginUser = (userData, history) => (dispatch) => {
dispatch({ type: LOADING_UI });
axios
.post("/login", userData)
.then((res) => {
const FBIdToken = `Bearer ${res.data.token}`;
localStorage.setItem("FBIdToken", `Bearer ${res.data.token}`);
axios.defaults.headers.common['Authorization'] = FBIdToken;
// dispatch(getUserData());
dispatch({ type: CLEAR_ERRORS })
history.push("/");
})
.catch(err => {
dispatch({
type: SET_ERRORS,
payload: err.response.data
})
});
}
export const logoutUser = () => (dispatch) => {
localStorage.removeItem('FBIdToken');
delete axios.defaults.headers.common['Authorization'];
dispatch({ type: SET_UNAUTHENTICATED })
}
export const getUserData = () => (dispatch) => {
axios.get('/user')
.then(res => {
dispatch({
type: SET_USER,
payload: res.data
})
})
.catch(err => console.log(err));
}
My app.js with routes
...
const token = localStorage.FBIdToken;
if (token) {
const decodedToken = jwtDecode(token);
if (decodedToken.exp * 1000 < Date.now()) {
store.dispatch(logoutUser());
window.location.href = "/login";
} else {
store.dispatch({ type: SET_AUTHENTICATED });
axios.defaults.headers.common["Authorization"] = token;
}
}
function App() {
document.documentElement.classList.remove("nav-open");
React.useEffect(() => {
document.body.classList.add("index");
return function cleanup() {
document.body.classList.remove("index");
};
});
return (
// <MuiThemeProvider theme={theme}>
<Provider store={store}>
<Router>
<div className="main">
<Switch>
<Route exact path="/" component={home} />
<Route exact path="/products" component={products} />
<Route exact path="/retreats" component={retreats} />
<Route exact path="/tarot" component={tarot} />
<Route
path="/artist"
render={props => <ProfilePage {...props} />}
/>
<Route exact path="/login" component={login} />
</Switch>
</div>
<Footer />
</Router>
</Provider>
// </MuiThemeProvider>
);
}
export default App;
And my login.jsx page component
import React, { Component } from "react";
...
export class login extends Component {
constructor(){
super();
this.state = {
email: '',
password: '',
errors: {}
}
}
componentWillReceiveProps(nextProps) {
if(nextProps.UI.errors) {
this.setState({ errors: nextProps.UI.errors })
}
}
handleSubmit = (event) => {
event.preventDefault();
const userData = {
email: this.state.email,
password: this.state.password
}
this.props.loginUser(userData, this.props.history);
}
handleChange = (event) => {
this.setState({
[event.target.name]: event.target.value
})
}
render() {
// loading was before: { classes, UI: { loading } }
const { classes, loading } = this.props;
const { errors } = this.state;
return (
<>
<IndexNavbar />
<ProfilePageHeader />
<Grid container className={classes.form}>
<Grid item sm />
<Grid item sm>
<ChangeHistoryIcon />
<Typography variant="h3" className={classes.pageTitle}>
Login
</Typography>
<form noValidate onSubmit={this.handleSubmit}>
<TextField
id="email"
name="email"
type="email"
label="Email"
className={classes.textField}
helperText={errors.email}
error={errors.email ? true : false}
value={this.state.email}
onChange={this.handleChange}
fullWidth
/>
<TextField
id="password"
name="password"
type="password"
label="Password"
className={classes.textField}
helperText={errors.password}
error={errors.password ? true : false}
value={this.state.password}
onChange={this.handleChange}
fullWidth
/>
{errors.general && (
<Typography variant="body2" className={classes.customError}>
{errors.general}
</Typography>
)}
<Button
type="submit"
variant="contained"
color="primary"
className={classes.button}
>
Login
{loading && (
<CircularProgress size={30} className={classes.progress} />
)}
</Button>
</form>
</Grid>
<Grid item sm />
</Grid>
</>
);
}
}
login.propTypes = {
classes: PropTypes.object.isRequired,
loginUser: PropTypes.func.isRequired,
user: PropTypes.object.isRequired,
UI: PropTypes.object.isRequired
}
const mapStateToProps = (state) => ({
user: state.user,
UI: state.UI
});
const mapActionsToProps = {
loginUser
}
export default connect(mapStateToProps, mapActionsToProps)(withStyles(styles)(login));
Does anybody know why I get this error when I'm obviously sending a post request?
any help is greatly appreciated!
ANDit was brought to my attention that it might be an issue with my backennd not rendering the index file? I'm not sure what to do here. this is my backend index file
const functions = require('firebase-functions');
const app = require('express')();
const FBAuth = require('./util/fbAuth')
const cors = require('cors');
app.use(cors());
const { getAllPosts, createOnePost, getThePost, deletePost, uploadImage } = require('./handlers/posts');
const { login } = require('./handlers/users');
// Posts Routes
app.get('/posts', getAllPosts);
app.get('/post/:postId', getThePost);
app.post("/post", FBAuth, createOnePost);
app.delete('/post/:postId', FBAuth, deletePost);
app.post('/post/:postId/image', FBAuth, uploadImage);
//TODO update post
// Login Route
app.post('/login', login)
exports.api = functions.https.onRequest(app)
So I assume you're using react router dom. Are you using < Link to='/login' >? or are you using another way that actually sends a get request such as an a tag?
React Router Dom needs you to use their components to navigate on the react side of things.