Async/await not working with react js(hooks) - javascript

I am trying to create a react application in which I am using react hooks.
In login form when the user submits the form email and password are passed to handleClick function.
That function fetches the data from the server and displays on client side but the response is always undefined and being called before return from service.
Here is the code...
Login.js
import React, { useState, useEffect } from 'react';
import { Button, Form, Container, Row, Col } from 'react-bootstrap';
import './login.css'
import * as services from '../services'
function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleClick = async(e) => {
e.preventDefault();
console.log(email, password);
let res = await services.login(email, password);
console.log(res);
}
return (
<Container>
<Row className="justify-content-md-center ">
<header><h2>Rao infotech workspace</h2></header>
</Row>
<Row className="justify-content-md-center form">
<Col md="auto">
<Form onSubmit={handleClick}>
<Form.Group controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control type="email" placeholder="Enter email" onChange={(e) => setEmail(e.target.value)} />
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} />
</Form.Group>
<Button variant="primary" type="submit" >
Submit
</Button>
</Form>
</Col>
</Row>
</Container>
);
}
export default Login;
services.js
import axios from "axios";
const baseUrl = "http://localhost:4000/";
export function login(email, password) {
var body = {email: email, password: password}
axios.post(baseUrl + 'user/login', body)
.then((res)=>{
console.log("res in service", res);
return res;
})
}
I tried using useEffect but coudn't get how to call function inside useEffect()

You need to return your loginfunction:
export async function login(email, password) {
var body = {email: email, password: password}
return axios.post(baseUrl + 'user/login', body)
.then((res)=>{
console.log("res in service", res);
return res;
})
}
Or simply:
export async function login(email, password) {
var body = {email: email, password: password}
return axios.post(baseUrl + 'user/login', body);
}

import axios from "axios";
const baseUrl = "http://localhost:4000/";
export function login(email, password) {
var body = {email: email, password: password}
return new Promise((resolve, reject) => {
axios.post(baseUrl + 'user/login', body)
.then((res)=>{
console.log("res in service", res);
return resolve(res);
});
})
}
Just create the promise in service your async/await will start working.

Your service.js login function is not returning a promise so you cannot await its result

Related

Got this error POST https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyAIAPVIvYAy4K20V5KgrEj4VESZ55ch6II 400

I am trying to upload signup data like image in firestore. I have setup firestore and storage in firebase although it gives this error.
"POST https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyAIAPVIvYAy4K20V5KgrEj4VESZ55ch6II 400"
what to do ? Can anyone please help?
My signup page:
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { Container, Row, Col, Form, FormGroup } from "reactstrap";
import Helmet from "../components/Helmet/Helmet";
import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import { setDoc, doc } from "firebase/firestore";
import { auth } from "../firebase.config";
import { storage } from "../firebase.config";
import { db } from "../firebase.config";
import { toast } from "react-toastify";
import "../styles/login.css";
const Signup = () => {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [file, setFile] = useState(null);
const [loading, setLoading] = useState(false);
const signupUser = async (e) => {
e.preventDefault();
setLoading(true);
try {
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password
);
const user = userCredential.user;
const storageRef = ref(storage, `images/${Date.now() + username}`);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
(error) => {
toast.error(error.message);
},
() => {
getDownloadURL(updateProfile.snapshot.ref).then(
async (downloadURL) => {
await updateProfile(user, {
displayName: username,
photoURL: downloadURL,
});
await setDoc(doc(db, "users", user.uid), {
uid: user.uid,
displayName: username,
email,
photoURL: downloadURL,
});
}
);
}
);
} catch (error) {
toast.error("something went wrong");
}
};
return (
<Helmet title="Signup">
<section>
<Container>
<Row>
<Col lg="6" className="m-auto text-center">
<h3 className="fw-bold mb-2">Signup</h3>
<Form className="auth__form" onSubmit={signupUser}>
<FormGroup className="form__group">
<input
type="text"
placeholder="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</FormGroup>
<FormGroup className="form__group">
<input
type="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</FormGroup>
<FormGroup className="form__group">
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</FormGroup>
<FormGroup className="form__group">
<input
type="file"
onChange={(e) => setFile(e.target.files[0])}
/>
</FormGroup>
<button type="submit" className="buy__btn auth__btn">
Create an account
</button>
<p>
Already have an account? <Link to="/login">Login</Link>
</p>
</Form>
</Col>
</Row>
</Container>
</section>
</Helmet>
);
};
export default Signup;
I think I have configured firebase correctly.

Checking if a user is logged in to use features on other pages

I have connected to an API to make users log in if they have an account. However, I have other pages which I want them to be logged in in order to use. How would I check to make sure a certain user is logged in to use certain features? Is there any source someone can guide me to? Any help would be appreciated.
Thanks,
import React, { useState, useEffect } from "react";
import ForgotPassword from "./ForgotPassword";
import TermsOfService from "./TermsOfService";
import axios from "axios";
function Login() {
const [user, setUser] = useState("");
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
function handleLogin() {
var config = {
method: "post",
url: "http://localhost:8080/api/account/login",
data: {
username: userName,
password: password,
},
};
axios(config)
.then(function (response) {
setUser(response.data);
localStorage.setItem("user", JSON.stringify(response.data));
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
}
return (
<>
<Navbar />
<div className="login_form">
<input
className="form_input"
type="text"
placeholder="Username or Email"
onChange={(e) => setUserName(e.target.value)}
/>
<input
className="form_input"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit" onClick={handleLogin} className="Signup_button">
Login
</button>
</div>
</>
);
}
export default Login;

how do we pass the user id into a route in app.js?

my teammate and I are stuck on solving a critical problem, which is how do we pass the user_id from one component to another in app.js . For example, we are able to register, login, and logout perfectly; but when we try to submit information in another component like personal form it says user_id is not defined. Also we are using JWT Tokens for authorization, and authentication. We are using local storage only, we did not implement redux.
App.js
import React, { Fragment, useState, useEffect } from "react";
import "./App.css";
import {
BrowserRouter as Router,
Routes,
Route,
Navigate,
} from "react-router-dom";
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
// import { useNavigation } from '#react-navigation/native';
import Home from "./components/Home";
import Login from "./components/Login";
import Register from "./components/Register";
import MedicalForm from "./components/MedicalForm";
import PersonalForm from "./components/PersonalForm";
import Navbar from "./components/Navbar/index";
toast.configure();
function App() {
// we want to make sure it set to false first
const [isAuthenticated, setAuthenticated] = useState(false);
//this is going to the be toggle function to set the auth
const setAuth = (Boolean) => {
setAuthenticated(Boolean);
};
// this is going to check if the user is authenticated even if the
// page is refreshed
async function isAuth() {
try {
const response = await fetch("http://localhost:4001/auth/is-verify", {
method: "GET",
headers: { token: localStorage.token },
});
const parseRes = await response.json();
parseRes === true ? setAuthenticated(true) : setAuthenticated(false);
console.log(parseRes);
} catch (err) {
console.error(err.message);
}
}
useEffect(() => {
isAuth();
});
return (
<Fragment>
<Router>
{/* reason why we use render instead of component props is because
anytime we send props to a component we don't want it to remount */}
<Navbar />
<div className="container">
<Routes>
{/* if(!isAuthenticated){ if this is true, pass setAuth to Login, and if it comes out true, then navigate to login page
<Login setAuth={setAuth} />}
else{
<Navigate to="/home" />
} */}
<Route
exact
path="/login"
element={
!isAuthenticated ? (
<Login setAuth={setAuth} />
) : (
<Navigate to="/home" />
)
}
/>
<Route
exact
path="/register"
element={
!isAuthenticated ? (
<Register setAuth={setAuth} />
) : (
<Navigate to="/login" />
)
}
/>
<Route
exact
path="/home"
element={
isAuthenticated ? (
<Home setAuth={setAuth} />
) : (
<Navigate to="/login" />
)
}
/>
<Route
exact
path="/mform"
element={
isAuthenticated ? (
<MedicalForm setAuth={setAuth} />
) : (
<Navigate to="/login" />
)
}
/>
<Route
exact
path="/pform"
element={
isAuthenticated ? (
<PersonalForm setAuth={setAuth} />
) : (
<Navigate to="/login" />
)
}
/>
</Routes>
</div>
</Router>
</Fragment>
);
}
export default App;
PersonalForm.js
`Login.js
import React, { Fragment, useState } from "react";
// import { Link } from "react-router-dom";
import { toast } from "react-toastify";
const Personalform = (props) => {
const [username, setUsername] = useState("");
const [inputs, setInputs] = useState({
first_name: "",
last_name: "",
pronoun: "",
occupation: "",
phone_number: "",
city: "",
state: "",
zip: "",
});
const {
first_name,
last_name,
pronoun,
occupation,
phone_number,
city,
state,
zip,
} = inputs;
const onChange = (e) => {
// take in every input and target the input value of name
//like email,username, and password
setInputs({ ...inputs, [e.target.name]: e.target.value });
};
const onSubmitForm = async (e) => {
e.preventDefault();
try {
const body = {
first_name,
last_name,
pronoun,
occupation,
phone_number,
city,
state,
zip,
};
// console.log(user_id)
const response = await fetch(
`http://localhost:4001/pform/${props.user_id}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
token: localStorage.token,
},
body: JSON.stringify(body),
}
);
const parseRes = await response.json();
setUsername(parseRes.username);
if (parseRes.token) {
// we want to save the token to our local storage
localStorage.setItem("token", parseRes.token);
console.log(parseRes);
//now we want to setAuth to true
props.setAuth(true);
toast.success("submit succesfully"); // then use toastify
} else {
// if false
props.setAuth(false); // set auth to false
toast.error(parseRes); // set the toast to send and error
}
} catch (err) {
console.error(err.message);
}
};
const logout = (e) => {
e.preventDefault();
localStorage.removeItem("token");
props.setAuth(false);
toast.success("Logged out successfully");
};
return (
<Fragment>
{username}
<h1 className="text-center my-5">Personal Form</h1>
<form onSubmit={onSubmitForm}>
<input
type="text"
// this is a name of an input
name="first_name"
placeholder="first_name"
className="form-control my-3"
value={first_name}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="last_name"
placeholder="Last Name"
className="form-control my-3"
value={last_name}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="pronoun"
placeholder="pronoun"
className="form-control my-3"
value={pronoun}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="occupation"
placeholder="occupation"
className="form-control my-3"
value={occupation}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="phone_number"
placeholder="phone number"
className="form-control my-3"
value={phone_number}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="city"
placeholder="city"
className="form-control my-3"
value={city}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="state"
placeholder="state"
className="form-control my-3"
value={state}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="zip"
placeholder="zip"
className="form-control my-3"
value={zip}
onChange={(e) => onChange(e)}
/>
<button className="btn btn-success btn-block">Submit</button>
</form>
<button className="btn btn-primary" onClick={(e) => logout(e)}>
logout
</button>
</Fragment>
);
};
export default Personalform;
index.js or the navbar component
import React from "react";
import {
Nav,
NavLink,
Bars,
NavMenu,
NavBtn,
NavBtnLink,
} from "./NavbarElements";
const Navbar = () => {
return (
<>
<Nav>
<NavLink to="/">
<h1>Logo</h1>
</NavLink>
<Bars />
<NavMenu>
<NavLink to="/pform" activeStyle>
Personal Form
</NavLink>
</NavMenu>
<NavBtn>
<NavBtnLink to="/login">Login</NavBtnLink>
</NavBtn>
</Nav>
</>
);
};
export default Navbar;
login.js
import React, { Fragment, useState } from "react";
import { Link } from "react-router-dom";
import { toast } from "react-toastify";
const Login = ({ setAuth }) => {
const [inputs, setInputs] = useState({
email: "",
password: "",
});
const { email, password } = inputs;
const onChange = (e) => {
setInputs({ ...inputs, [e.target.name]: e.target.value });
};
const onSubmitForm = async (e) => {
e.preventDefault();
try {
const body = { email, password };
const response = await fetch("http://localhost:4001/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const parseRes = await response.json();
if (parseRes.token) {
localStorage.setItem("token", parseRes.token);
setAuth(true);
toast.success("login successfully!");
} else {
setAuth(false);
toast.error(parseRes);
}
} catch (err) {
console.error(err.message);
}
};
return (
<Fragment>
<h1>Login</h1>
<form onSubmit={onSubmitForm}>
<input
type="email"
name="email"
placeholder="email"
className="form-control my-3"
value={email}
onChange={(e) => onChange(e)}
/>
<input
type="password"
name="password"
placeholder="password"
className="form-control my-3"
value={password}
onChange={(e) => onChange(e)}
/>
<button className="btn btn-success btn-block">submit</button>
</form>
<Link to="/register">Register</Link>
</Fragment>
);
};
export default Login;
Register
import React, { Fragment, useState } from "react";
import { Link } from "react-router-dom";
import { ToastContainer, toast } from "react-toastify";
const Register = ({ setAuth }) => {
const [inputs, setInputs] = useState({
email: "",
password: "",
username: "",
});
const { email, password, username } = inputs;
const onChange = (e) => {
// take in every input and target the input value of name
//like email,username, and password
setInputs({ ...inputs, [e.target.name]: e.target.value });
};
const onSubmitForm = async (e) => {
e.preventDefault();
try {
const body = { email, password, username };
const response = await fetch("http://localhost:4001/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const parseRes = await response.json();
if (parseRes.token) {
localStorage.setItem("token", parseRes.token);
setAuth(true);
toast.success("Registered Successfully!");
} else {
setAuth(false);
toast.error(parseRes);
}
} catch (err) {
console.error(err.message);
}
};
return (
<Fragment>
<h1 className="text-center my-5">Register</h1>
<form onSubmit={onSubmitForm}>
<input
type="email"
// this is a name of an input
name="email"
placeholder="email"
className="form-control my-3"
value={email}
onChange={(e) => onChange(e)}
/>
<input
type="password"
name="password"
placeholder="password"
className="form-control my-3"
value={password}
onChange={(e) => onChange(e)}
/>
<input
type="text"
name="username"
placeholder="username"
className="form-control my-3"
value={username}
onChange={(e) => onChange(e)}
/>
<button className="btn btn-success btn-block">Submit</button>
</form>
<Link to="/login">Login</Link>
</Fragment>
);
};
export default Register;
jwtauth.js
const router = require("express").Router();
const { json, response } = require("express");
const pool = require("../db");
const bcrypt = require("bcrypt");
const jwtGenerator = require("../utils/jwtGenerator");
const validInfo = require("../middleware/validInfo");
const authorization = require("../middleware/authorization");
//registering
router.post("/register", validInfo, async (req, res) => {
try {
// 1. destructure the req.body(name,email,password)
const { username, email, password } = req.body;
// 2. check if user exists (if user exists then throw error)
const user = await pool.query(
"SELECT * FROM login_credentials WHERE email =$1",
[email]
);
if (user.rows.length !== 0) {
return res.status(401).json("User already exists");
}
// res.json(user.rows);
// 3. bycrpyt the user password
const saltRound = 10;
const salt = await bcrypt.genSalt(saltRound);
const bcryptPassword = await bcrypt.hash(password, salt);
// 4. enter the new user inside our database
const newUser = await pool.query(
"INSERT INTO login_credentials (username,email,password) VALUES ($1,$2,$3) RETURNING *",
[username, email, bcryptPassword]
);
// res.json(newUser.rows[0]);
// 5. generate our jwt token
const token = jwtGenerator(newUser.rows[0].user_id);
res.json({ token });
} catch (err) {
console.error(err.message);
res.status(500).send("server error");
}
});
//login route
router.post("/login", validInfo, async (req, res) => {
try {
//1. destructure the req.body
const { email, password } = req.body;
//2. check if user doesn't exist (if not we throw error)
const user = await pool.query(
"SELECT * FROM login_credentials WHERE email=$1",
[email]
);
if (user.rows.length === 0) {
return res.status(401).json("password or email is incorrect");
}
//3. check if incoming password is the same the database password
const validPassword = await bcrypt.compare(password, user.rows[0].password);
console.log(validPassword);
if (!validPassword) {
return res.status(401).json("password or email is incorrect");
}
//4. give the jwt token
const token = jwtGenerator(user.rows[0].user_id);
res.json({ token });
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
router.get("/is-verify", authorization, async (req, res) => {
try {
res.json(true);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
module.exports = router;
authorization.js
const jwt = require("jsonwebtoken");
require("dotenv").config();
// before it hits routes it's going to get access to the requested
// resonse then if everything ends up working ok, it will continue on
// with the process of next so it can keep going with the routes
module.exports = async (req, res, next) => {
try {
const jwtToken = req.header("token");
if (!jwtToken) {
return res.status(401).json("Not Authorized");
}
// if this is verified it is going to return us a payload that we can use within our routes
const payload = jwt.verify(jwtToken, process.env.jwtSecret);
req.user = payload.user;
next();
} catch (err) {
console.error(err.message);
return res.status(403).json("Not Authorized");
}
};
validInfo.js
module.exports = (req, res, next) => {
const { email, username, password } = req.body;
function validEmail(userEmail) {
return /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(userEmail);
}
if (req.path === "/register") {
if (![email, username, password].every(Boolean)) {
return res.status(401).json("Missing Credentials");
} else if (!validEmail(email)) {
return res.status(401).json("Invalid Email");
}
} else if (req.path === "/login") {
if (![email, password].every(Boolean)) {
return res.status(401).json("Missing Credentials");
} else if (!validEmail(email)) {
return res.status(401).json("Invalid Email");
}
}
next();
};
you can create a file for auth context then create a context and export it
export const AuthContext= React.createContext({userId:"",setUserId: ()=>{}}); //the param here should be the default value (default shape of the object you wanna pass to children)
Then in your app.js import that context and wrap your other components with
const [userId, setUserId] = useState("");
<AuthContext.Provider value={{userId:userId, setUserId:setUserId}}> //the object contains the state or functions you wanna access from child components
//your other components
</AuthContext.Provider>
now inside any screen or component that needs to access or set the user id (or any other value or callback you passed) you can just import the context and access the value like this
const {userId,setUserId} = useContext(AuthContext)
you can also refer to this example:
https://fatmali.medium.com/use-context-and-custom-hooks-to-share-user-state-across-your-react-app-ad7476baaf32
You can set vars in res object like this in node.js. But it your code is react not node.js.
res.user.user_id = user_id;
and then use it anywhere with:
let user_id = res.user.user_id;

how i validate if the user has a token in localStorage

My app calls a Login api and returns me a token,i stored the token in localStorage so my problem is how i validade if the user has a token to do the login. what can i do to do that?
this is my login Page where i used to add the token to the localStorage
import React, { useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { login } from '../services/login.services';
function Login() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const history = useHistory();
const loginHandler = async () => {
const result = await login(email, password);
console.log(result);
localStorage.setItem('token', result?.response?.result?.token);
localStorage.getItem('token');
};
return (
<section className='layout'>
<div className='wrp-login'>
<div className='container'>
<h1 color='white'>Login Page</h1>
<div className='col-sm-6 offset-sm-3'>
<input
type='text'
placeholder='email'
onChange={(e) => setEmail(e.target.value)}
className='input-wrapper'
/>
<br />
<input
type='password'
placeholder='password'
onChange={(e) => setPassword(e.target.value)}
className='input-wrapper'
/>
<br />
<button onClick={() => loginHandler()} className='button'>
Login
</button>
</div>
</div>
</div>
</section>
);}export default Login;
this is my Login Service wher i do the api call and return data
export const login = async (email, password) => {
try {
const result = await fetch(
'teste.com',
{
method: 'Post',
body: JSON.stringify({ login: email, senha: password }),
headers: {
'Content-Type': 'application/json',
},
mode: 'cors',
cache: 'default',
},
);
return await result.json();
} catch (err) {
return err;
}};
Someone could help me?
You can validate and redirect users by creating a wrapper for protected routes with react-router-dom to the login page if they don't have the token stored this way:
const ProtectedRoute = (props) => {
const token = localStorage.getItem('token');
if (token == null) {
return <Redirect to={Routes.LOGIN} />;
}
return <>{props.children}</>;
};

How do t use match props in react js while using context api

I'm creating a basic app and i used context api, fetch, react hooks for all the component except the context api component because, i'm still learning to use hooks.
I fetched my data from the backend, i want to use one component for my create and update of my data, my major problem is that i don't know how to use the match prop inside the contextApi provider to get the id for editform and singleItem using params. I created a function that calls a singleItem and i passed it to my form component, so it can be the initial value in case of editing but it didn't work. I got an error Unhandled Rejection (TypeError): Cannot read property 'params' of undefined.
my context api component
import React, { Component, createContext } from 'react'
export const ContactContext = createContext()
export class ContactContextProvider extends Component {
state = {
Contact : [],
singleContact:{}
}
componentDidMount(){
fetch('http://127.0.0.1:5000/Contact')
.then(res=>res.json())
.then(data=>{
this.setState({
Contact:data
})
})
this.getSingleItem()
}
getSingleItem = async() => {
const fetch_id = await fetch(`http://127.0.0.1:5000/Contact/${this.props.match.params.id}`)
const data = await fetch_id.json()
this.setState({singleContact:data})
}
createContact = (item) =>{
const req = {
method : 'POST',
headers : {'Content-Type':'application/json'},
body: JSON.stringify(item)
}
fetch('http://127.0.0.1:5000/Contact/add', req)
.then(res=>res.json())
.then(data=> data)
}
editContact = (item) => {
const req = {
method : 'POST',
headers : {'Content-Type' : 'application/json'},
body : JSON.stringify(item)
}
fetch(`http://127.0.0.1:5000/Contact/edit/${this.props.match.params.id}`)
.then(res=>res.json())
.then(data=>console.log(data))
}
deleteContact = (_id) => {
fetch(`http://127.0.0.1:5000/Contact/${_id}`, {method:'DELETE'})
.then(res=>res.json())
.then(data=>console.log(data))
this.setState({
Contact : [...this.state.Contact.filter(item => item._id !== _id)]
})
}
render() {
return (
<ContactContext.Provider value={{...this.state, createContact:this.createContact, editContact:this.editContact, deleteContact:this.deleteContact}}>
{this.props.children}
</ContactContext.Provider>
)
}
}
export default ContactContextProvider
This is my form for creating and editing data
import { Form, Button, Col} from 'react-bootstrap';
import React, {useState, useContext} from 'react'
import { ContactContext } from '../context/ContactContext';
function Contactform() {
const {createContact, singleContact, editContact} = useContext(ContactContext)
const [Contact, setContact] = useState({
firstName: singleContact.firstName || '',
lastName: singleContact.lastName || '',
company: singleContact.company || '',
phone: singleContact.phone || '',
email: singleContact.email || '',
note: singleContact.note || ''
})
const handleChange = (e) =>{
setContact((prevState)=>({
...prevState,
[e.target.name]:e.target.value
}))
}
const handleSubmit = (e) =>{
e.preventDefault()
const item = {
firstName: Contact.firstName,
lastName: Contact.lastName,
company: Contact.company,
phone: Contact.phone,
email: Contact.email,
note: Contact.note
}
if(Contact===''){
createContact(item)
}
else {
editContact(item)
}
}
return (
<Form id='form' onSubmit={handleSubmit} >
<Form.Row>
<Form.Group as={Col} >
<Form.Label>First Name</Form.Label>
<Form.Control name='firstName' value={Contact.firstName} onChange={handleChange} type="text" placeholder="First Name" />
</Form.Group>
<Form.Group as={Col} >
<Form.Label>Last Name</Form.Label>
<Form.Control name='lastName' value={Contact.lastName} onChange={handleChange} type="text" placeholder="Last Name" />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} >
<Form.Label>Company</Form.Label>
<Form.Control name='company' value={Contact.company} onChange={handleChange} type="text" placeholder="Company" />
</Form.Group>
<Form.Group as={Col} >
<Form.Label>Phone</Form.Label>
<Form.Control name='phone' value={Contact.phone} onChange={handleChange} type="text" placeholder="Phone" />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} >
<Form.Label>Email</Form.Label>
<Form.Control name='email' type="email" value={Contact.email} placeholder=" email" onChange={handleChange} />
</Form.Group>
</Form.Row>
<Form.Group >
<Form.Label>Note</Form.Label>
<Form.Control as="textarea" name='note' value={Contact.note} onChange={handleChange} rows={3} placeholder='Note'/>
</Form.Group>
<Button id='form_btn' variant="primary" type="submit">
Submit
</Button>
</Form>
)
}
export default Contactform
You can simply do this. I am assuming you are already using react-router.
You can simply use withRouter hoc. It will pass all router props.
//Your context api component
import React, { Component, createContext } from 'react'
import { withRouter } from "react-router";
export const ContactContext = createContext()
class ContactContextProvider extends Component {
state = {
Contact : [],
singleContact:{}
}
componentDidMount(){
fetch('http://127.0.0.1:5000/Contact')
.then(res=>res.json())
.then(data=>{
this.setState({
Contact:data
})
})
this.getSingleItem()
}
getSingleItem = async() => {
const fetch_id = await fetch(`http://127.0.0.1:5000/Contact/${this.props.match.params.id}`)
const data = await fetch_id.json()
this.setState({singleContact:data})
}
createContact = (item) =>{
const req = {
method : 'POST',
headers : {'Content-Type':'application/json'},
body: JSON.stringify(item)
}
fetch('http://127.0.0.1:5000/Contact/add', req)
.then(res=>res.json())
.then(data=> data)
}
editContact = (item) => {
const req = {
method : 'POST',
headers : {'Content-Type' : 'application/json'},
body : JSON.stringify(item)
}
fetch(`http://127.0.0.1:5000/Contact/edit/${this.props.match.params.id}`)
.then(res=>res.json())
.then(data=>console.log(data))
}
deleteContact = (_id) => {
fetch(`http://127.0.0.1:5000/Contact/${_id}`, {method:'DELETE'})
.then(res=>res.json())
.then(data=>console.log(data))
this.setState({
Contact : [...this.state.Contact.filter(item => item._id !== _id)]
})
}
render() {
return (
<ContactContext.Provider value={{...this.state, createContact:this.createContact, editContact:this.editContact, deleteContact:this.deleteContact}}>
{this.props.children}
</ContactContext.Provider>
)
}
}
export default withRouter(ContactContextProvider)

Categories