React Hooks - How can I pass props from child to parent component - hook

I want to pass the form data from a child component to a parent component, so I can use them inside the parent component. But don't know how to do so.
Child component
import React, { useState } from 'react';
const InputForm = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
};
return (
<>
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Control
type='text'
value={name}
onChange={(e) => setName(e.target.value)}
/>
</Form.Group>
<Form.Group>
<Form.Control
type='email'
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<Button type='submit'>
Submit
</Button>
</Form>
</>
);
};
export default InputForm;
Parent component
import React from 'react';
import InputForm from './InputForm';
const App = () => {
return (
<div className='App'>
<InputForm />
Name is {name}
Email is {email}
</div>
);
};
export default App;

You got two options.You can either implement redux or something similar to decouple the state, or you can pass down a callback to you child to pass the form data back to your parent component

Related

login page authentication ReactJs

Here i want to integrate API for my login page.
Frontend code on ReactJS:
import React, { useState, useEffect } from "react";
import Axios from "axios";
import SignUp from './signup';
const Login = () => {
const [products, setProducts] = useState([]);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = async () => {
console.log("success0");
const { data } = await Axios.get(
"http://localhost:8080/api/login/"+email
);
let parseData = JSON.parse(data.response);
setProducts(parseData);
if(products.password==password){
//render to sign up page
}
};
return (
<form onSubmit={handleSubmit} >
<h3>Sign In</h3>
<div className="mb-3">
<label>Email</label>
<input
type="email"
className="form-control"
placeholder="Enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="mb-3">
<label>Password</label>
<input
type="password"
className="form-control"
placeholder="Enter password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="d-grid">
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
</form>
)
}
export default Login;
here i taking email and password from the user and through email if i am searching data of the user then i am matching the password. If the password get matched i need to render it to signup page.
please make sure you use react-router-dom version ^6.2.2
in your handleSubmit add this code and import react-router-dom
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
if(products.password==password){
navigate(`/anyroute`)
}

A question about the onSubmit function in the react application standing on the node.js server

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>

"No routes matched location" error in React

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.

How can I map string array taken from mongoDB and show one specific title/body per post

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;

Why did it failed to load? the server responded with a status of 404 (Not Found)

I have my app(express+Next.js.MOngoDB).I signuped all my users,works Ok. Now when I try signin
http://localhost:5000/signin
I got error
Uncaught (in promise) Error: Request failed with status code 404
at createError (webpack-internal:///../../node_modules/axios/lib/core/createError.js:16)
at settle (webpack-internal:///../../node_modules/axios/lib/core/settle.js:17)
Terminal
GET /__nextjs_original-stack-frame?isServerSide=false&file=webpack-internal%3A%2F%2F%2F..%2F..%2
POSTMAN signin works fine
app.js(just API)
const app = express();
app.use('/api/v1/auth', auth);
Next.js,Signin
import SigninComponent from '../components/frontauth/SigninComponent';
const Signin = () => {
return (
<Layout>
<h2 className="text-center pt-3 pb-4">Signin</h2>
<div className="row">
<div className="col-md-6 offset-md-3">
<SigninComponent />
</div>
</div>
</Layout>
);
};
SigninComponent
/* eslint-disable no-undef */
import axios from 'axios';
import React, { useState } from 'react';
import { API } from '../../config';
const SigninComponent = () => {
const [values, setValues] = useState({
email: '',
password: ''
});
const [loading, setLoading] = useState(false);
const { email, password } = values;
const handleSubmit = async (e) => {
e.preventDefault();
const { email, password } = values;
const user = { email, password};
await axios.post(`${API}/api/v1/auth/signin`, user);
};
const handleChange = name => e => {
setValues({ ...values, error: false, [name]: e.target.value });
};
const showLoading = () => (loading ? <div className="alert alert-info">Loading...</div> : '');
const signinForm = () => {
return (
<form onSubmit={handleSubmit}>
<div className="form-group">
<input
value={values.email}
onChange={handleChange('email')}
type="email"
className="form-control"
placeholder="Type your email"
/>
</div>
<div className="form-group">
<input
value={values.password}
onChange={handleChange('password')}
type="password"
className="form-control"
placeholder="Type your password"
/>
</div>
<div>
<button className="btn btn-primary">Signin</button>
</div>
</form>
);
};
return <React.Fragment>
{showLoading()}
{signinForm()}
</React.Fragment>;
};
export default SigninComponent;
How should I edit .babelrc,I have only one line,should I add plugins?
"presets": ["next/babel"]
Why does the terminal point to SSR FALSE?

Resources