MERN AI image generation app not working after hosting - javascript

MY mern application was working fine in localhost but after hosting with render and 000webhost im getting error called as TypeError: failed to fetch and the console is showing these errors:
:1
Access to fetch at 'https://astroshock.onrender.com/api/v1/post' from origin 'https://astroshock.000webhostapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
astroshock.onrender.com/api/v1/post:1
Failed to load resource: net::ERR_FAILED
localhost:8080/api/v1/dalle:1
Failed to load resource: net::ERR_CONNECTION_REFUSED
create-post:1
Failed to load resource: the server responded with a status of 404 ()
This is my CreatePost page
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { preview } from '../assets';
import { getRandomPrompt } from '../utils';
import { FormField, Loader } from '../components';
const CreatePost = () => {
const navigate = useNavigate();
const [form, setForm] = useState({
name: '',
prompt: '',
photo: '',
});
const [generatingImg, setGeneratingImg] = useState(false);
const [loading, setLoading] = useState(false);
const handleChange = (e) => setForm({ ...form, [e.target.name]: e.target.value });
const handleSurpriseMe = () => {
const randomPrompt = getRandomPrompt(form.prompt);
setForm({ ...form, prompt: randomPrompt });
};
const generateImage = async () => {
if (form.prompt) {
try {
setGeneratingImg(true);
const response = await fetch('https://astroshock.onrender.com/api/v1/dalle', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: form.prompt,
}),
});
const data = await response.json();
setForm({ ...form, photo: `data:image/jpeg;base64,${data.photo}` });
} catch (err) {
alert(err);
} finally {
setGeneratingImg(false);
}
} else {
alert('Please provide proper prompt');
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (form.prompt && form.photo) {
setLoading(true);
try {
const response = await fetch('https://astroshock.onrender.com/api/v1/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ ...form }),
});
await response.json();
alert('Success');
navigate('/');
} catch (err) {
alert(err);
} finally {
setLoading(false);
}
} else {
alert(' You didn\'t train your imaginations properly ');
}
};
return (
<section className="max-w-7xl mx-auto">
<div>
<h1 className="font-extrabold text-[#22232d] text-[32px] bg-">Train</h1>
<p className="mt-2 text-[#666e75] text-[14px] max-w-[500px]">Play with your imaginations with AstroShock</p>
</div>
<form className="mt-16 max-w-3xl" onSubmit={handleSubmit}>
<div className="flex flex-col gap-5">
<FormField
labelName="Your Name"
type="text"
name="name"
placeholder="Enter your name..."
value={form.name}
handleChange={handleChange}
/>
<FormField
labelName="Prompt"
type="text"
name="prompt"
placeholder="panda mad scientist mixing sparkling chemicals, digital art"
value={form.prompt}
handleChange={handleChange}
isSurpriseMe
handleSurpriseMe={handleSurpriseMe}
/>
<div className="relative bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 w-64 p-3 h-64 flex justify-center items-center">
{ form.photo ? (
<img
src={form.photo}
alt={form.prompt}
className="w-full h-full object-contain"
/>
) : (
<img
src={preview}
alt="preview"
className="w-9/12 h-9/12 object-contain opacity-40"
/>
)}
{generatingImg && (
<div className="absolute inset-0 z-0 flex justify-center items-center bg-[rgba(0,0,0,0.5)] rounded-lg">
<Loader />
</div>
)}
</div>
</div>
<div className="mt-5 flex gap-5">
<button
type="button"
onClick={generateImage}
className=" text-white bg-sky-700 font-medium rounded-md text-sm w-full sm:w-auto px-5 py-2.5 text-center"
>
{generatingImg ? 'Generating...' : 'Generate'}
</button>
</div>
<div className="mt-10">
<p className="mt-2 text-[#666e75] text-[14px]">Share your imaginations with others</p>
<button
type="submit"
className="mt-3 text-amber-300 bg-[#1b1c3c] font-medium rounded-md text-sm w-full sm:w-auto px-5 py-2.5 text-center"
>
{loading ? 'Sharing...' : 'Share with everyone'}
</button>
</div>
</form>
</section>
);
};
export default CreatePost;
This is my HOme page
import React, { useEffect, useState } from 'react';
import { Card, FormField, Loader } from '../components';
const RenderCards = ({ data, title }) => {
if (data?.length > 0) {
return (
data.map((post) => <Card key={post._id} {...post} />)
);
}
return (
<h2 className="mt-5 font-bold text-[#6469ff] text-xl uppercase">{title}</h2>
);
};
const Home = () => {
const [loading, setLoading] = useState(false);
const [allPosts, setAllPosts] = useState(null);
const [searchText, setSearchText] = useState('');
const [searchTimeout, setSearchTimeout] = useState(null);
const [searchedResults, setSearchedResults] = useState(null);
const fetchPosts = async () => {
setLoading(true);
try {
const response = await fetch('https://astroshock.onrender.com/api/v1/post', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
const result = await response.json();
setAllPosts(result.data.reverse());
}
} catch (err) {
alert(err);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchPosts();
}, []);
const handleSearchChange = (e) => {
clearTimeout(searchTimeout);
setSearchText(e.target.value);
setSearchTimeout(
setTimeout(() => {
const searchResult = allPosts.filter((item) => item.name.toLowerCase().includes(searchText.toLowerCase()) || item.prompt.toLowerCase().includes(searchText.toLowerCase()));
setSearchedResults(searchResult);
}, 500),
);
};
return (
<section className="max-w-7xl mx-auto">
<div>
<h1 className="font-extrabold text-[#222328] text-[32px]">AstroShock Armoury</h1>
<p className="mt-2 text-[#666e75] text-[14px] max-w-[500px]">Play with the weapons in AstroShock's Armoury</p>
</div>
<div className="mt-16">
<FormField
labelName="Search posts"
type="text"
name="text"
placeholder="Search something..."
value={searchText}
handleChange={handleSearchChange}
/>
</div>
<div className="mt-10">
{loading ? (
<div className="flex justify-center items-center">
<Loader />
</div>
) : (
<>
{searchText && (
<h2 className="font-medium text-[#666e75] text-xl mb-3">
Showing Resuls for <span className="text-[#222328]">{searchText}</span>:
</h2>
)}
<div className="grid lg:grid-cols-4 sm:grid-cols-3 xs:grid-cols-2 grid-cols-1 gap-3">
{searchText ? (
<RenderCards
data={searchedResults}
title="No Search Results Found"
/>
) : (
<RenderCards
data={allPosts}
title="No Posts Yet"
/>
)}
</div>
</>
)}
</div>
</section>
);
};
export default Home;
This is the app page
import React from 'react';
import { BrowserRouter, Link, Route, Routes } from 'react-router-dom';
import { logo } from './assets';
import { Home, CreatePost } from './page';
const App = () => (
<BrowserRouter>
<header className="w-full flex justify-between items-center bg-white sm:px-8 px-4 py-4 border-b border-b-[#9805a0]">
<Link to="/">
<img src={logo} alt="logo" className="w-28 object-contain" />
</Link>
<Link to="/create-post" className="font-inter font-medium bg-[#070a50] text-cyan-300 px-4 py-2 rounded-md">Play</Link>
</header>
<main className="sm:p-8 px-4 py-8 w-full bg-[#f9fafe] min-h-[calc(100vh-73px)]">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/create-post" element={<CreatePost />} />
</Routes>
</main>
</BrowserRouter>
);
export default App;

I guess usually your error that is "url has been blocked by CORS policy" mean your request not sended from server side

Related

Having little complication while using useLocation() [duplicate]

This question already has answers here:
How to pass data from a page to another page using react router
(5 answers)
Closed 27 days ago.
I do not now why the same code was working yesterday fine but today not working. I understand why the error happens, but have no idea how to fix it. I am trying to redirect the user to profile component using Navigate comp with a state pass. This works fine, but when a user manually clicks on profile I get the error because I am trying to access the state value that does not exist. Since the state value is defined after only redirecting. So is there any help to avoid or fix this error?
react-refresh-runtime.development.js:315 Uncaught TypeError:
Cannot read properties of null (reading 'mes')
Login.jsx
import { useState } from "react";
import { Link, Navigate, Outlet } from "react-router-dom";
import axios from "axios";
import { FaEye, FaEyeSlash } from "react-icons/fa";
function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [inputType, setInputType] = useState("password");
const [icon, setIcon] = useState(<FaEye />);
const [success, setSuccess] = useState("");
const [result, setResult] = useState(false);
function handleToggle(e) {
if (inputType === "password") {
setInputType("text");
setIcon(FaEyeSlash);
} else {
setInputType("password");
setIcon(FaEye);
}
}
function handleSubmit(e) {
e.preventDefault();
const user = { email, password };
console.log(`email: ${email}, password: ${password}`);
axios
.post("http://localhost:5000/user/login", user)
.then((res) =>{
setResult(true);
setSuccess(`welcome ${res.data.user} you are successfully Logged in!`);
console.log(result);
}
)
.catch((err) => {
//console.log(`ERROR is ${err}`);
setResult(false);
console.log(result);
setSuccess("Incorrect password or email");
});
}
if(result){
console.log(result);
return <Navigate to="/profile" state={{mes: success }} />
}
return (
<form onSubmit={handleSubmit}>
<div className="text-center text-lg text-red-500 font-semibold">{success}</div>
<div className="h-auto w-5/12 border mx-auto rounded-2xl mt-3 ">
<div className="h-2 bg-indigo-400 rounded-t-2xl mb-5 "></div>
<div className="font-bold text-2xl text-center">Sign In</div>
<div className="px-16">
<div className="mt-5 ">
<label htmlFor="email" className="block font-semibold ">
Email address
</label>
<input
type="email"
className="border h-5 w-full px-3 py-5 rounded-md focus:outline-2 focus:outline-blue-600"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter email"
id="email"
required
/>
</div>
<div className="relative ">
<label
htmlFor="pass"
className="block font-semibold mt-5"
>
Password
</label>
<input
type={inputType}
className="border h-5 w-full px-3 py-5 rounded-md focus:outline-2 focus:outline-blue-600"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter password"
id="pass"
required
/>
<span className="absolute top-9 right-6" onClick={handleToggle}>
{icon}
</span>
</div>
<div className="">
<button
type="submit"
className="mt-5 text-white bg-blue-600 border h-10 w-full py-2 rounded-md"
>
Submit
</button>
</div>
<div className="flex justify-around">
<p className="mb-5 mt-3 text-left">
New here?
<Link to="/sign-up" className="text-blue-600">
Register
</Link>
</p>
<p className="mb-5 mt-3 text-right ">
Forgot
<Link to="/password-reset" className="text-blue-600">
password?
</Link>
</p>
</div>
</div>
</div>
</form>
);
}
export default Login;
Profile.jsx
import { useState } from "react";
import { useLocation } from "react-router-dom";
function Profile() {
const location = useLocation();
const msg = location.state.mes;
const [success, setSuccess] = useState(msg);
const [cancel, setCancel] = useState("X");
const [name, setName] = useState(
"h-10 flex justify-around items-center bg-green-200 text-black"
);
function handleClick() {
setSuccess("");
setCancel("");
setName("");
}
return (
<>
<div className={name}>
{success}
<button onClick={handleClick}>{cancel}</button>
</div>
profile
</>
);
}
export default Profile;
I have not tried anything, but I will try to see the docs on this.
Simply use Optional Chaining to check if location.state.mes exists. If location.state or location.state.mes doesn't exist then default to an empty string in the useState() call.
const msg = location.state?.mes; // msg will either be undefined or the message value
const [success, setSuccess] = useState(msg == undefined ? '' : msg);

I'm getting a unauthorised message when i try to login at the client side

I'm working on a Auth with MERN , at the client side i'm using contextAPI ,useReducerhook to manage the user.
I have also created a custom hook ( useLogin ) for handling the login criteria as shown below .It takes the userCredentials whoch is a object of (email password) from the login form .I have also incorporated the reacy-hook form to handle validation of the input fields
import axios from "axios";
import { BASE_API_URL } from "../utils/BaseUrl";
import { useAuthContext } from "./useAuthContext";
export const useLogin = () => {
const [isError, setIsError] = useState(null)
const [isLoading, setIsLoading] = useState(false)
const [IsSuccess, setIsSucces] = useState(false)
const { dispatch } = useAuthContext()
const loginUser = async (userDetails) => {
setIsError(null)
setIsLoading(true)
try {
const response = await axios.post(`${BASE_API_URL}/api/auth/login`, {
userDetails: userDetails
})
//get json data
const jsonData = await response.json()
//if there is a error in the response
if (!response.ok) {
setIsLoading(false)
setIsError(jsonData.error)
}
//if it works correctly
if (response.ok) {
//save user to local storage
localStorage.setItem("userData", JSON.stringify(jsonData));
localStorage.setItem("accessToken", jsonData.data?.accessToken)
//update the auth context
dispatch({ type: "LOGIN", paylaod: jsonData })
setIsLoading(false)
setIsSucces(true)
}
} catch (err) {
setIsError(err.message)
setIsLoading(false)
}
}
return { isError, isLoading, IsSuccess, loginUser }
}
Then i re use it at my login page as shown here
import ScaleLoader from "react-spinners/ScaleLoader";
import Logo from "../../assets/images/Logo.png";
import Footer from "../Footer/index";
import { Link } from "react-router-dom";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import Input from "#material-ui/core/Input";
import Swal from "sweetalert2";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faEye, faEyeSlash } from "#fortawesome/free-solid-svg-icons";
import { useLogin } from "../../hooks/useLogin";
const Login = () => {
const [userDetails, setUserDetails] = useState("");
const [passwordShown, setPasswordShown] = useState(false);
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
const navigate = useNavigate();
const { loginUser } = useLogin()
// Password toggle handler
const togglePassword = () => {
setPasswordShown(!passwordShown);
};
//handleSubmit
const onSubmit = async () => {
await loginUser(userDetails)
navigate("/user/dashboard");
setUserDetails('')
};
return (
<>
{/* <div className="d-flex justify-content-center loader">
<ScaleLoader
className="d-flex justify-content-center"
color="#FFC247"
speedMultiplier={4}
/>
</div> */}
<div className="login-page">
<div className="container">
<div className="row">
<div className="col-lg-6 offset-lg-3 col-md-12 offset-md-1 col-sm-12 offset-sm-1 col-xs-6 offset-xs-3">
<div className="login-form">
<div className="login-form-header d-flex flex-column justify-content-center flex-column align-items-center">
<img src={Logo} alt="" />
<h4>We missed you , glad to see you back</h4>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-group">
<label htmlFor="email1">Email address</label>
<input
type="email"
className={`form-control py-2 my-2 ${errors.email ? "input-error" : ""
}`}
id="email"
name="email"
placeholder="Enter email"
{...register("email", {
required: "Email is required",
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: "Invalid email address",
},
})}
/>
{errors.email && (
<span className="errorMsg">{errors.email.message}</span>
)}
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<div className="input-group">
<Input
type={passwordShown ? "text" : "password"}
className="form-control py-2 my-2"
id="password"
name="password"
placeholder="Enter password"
{...register("password", {
required: "Password is required",
minLength: {
value: 8,
message: "Password must be at least 8 characters",
},
pattern: {
value:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##$%^&*])/,
message:
"Password must contain at least one lowercase letter, one uppercase letter, one number and one special character",
},
})}
/>
<span
style={{ height: "50px", marginTop: "8px" }}
className="input-group-text"
onClick={togglePassword}
>
{passwordShown ? (
<FontAwesomeIcon icon={faEyeSlash} />
) : (
<FontAwesomeIcon icon={faEye} />
)}
</span>
</div>
{errors.password && (
<span className="errorMsg">
{errors.password.message}
</span>
)}
</div>
<div className="submit-button d-flex align-items-center justify-content-between mt-5">
<button className="btn-home px-5 rounded">Login</button>
<div className="forget-password">
<Link
to="/user/forgetpassword"
className="text-decoration-none text-link"
>
Forget my password
</Link>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div className="footer-home">
<Footer />
</div>
</div>
</>
);
};
export default Login;

(Next.js) Passing state object from an array mapping to router query when rerouting. TypeError: Cannot read properties of undefined (reading 'name')

How do I pass each coin being mapped through to state so when routed to the CoinInfo.jsx page I can pass 'coin' as a prop when calling sendProps in CoinSearch.jsx. So I can have access to the the coin's attributes on the CoinInfo page and can provide data to the user relating to the 'coin' being mapped through in CoinSearch.jsx
Full Error.
Github Rep: https://github.com/masonrs2/crypto-coin-search
CoinSearch.jsx
import React, { useEffect, useState } from 'react'
import { AiOutlineStar, AiFillStar } from 'react-icons/ai'
import { Sparklines, SparklinesLine } from 'react-sparklines';
import Router from 'next/router'
import Link from 'next/link'
import Signup from '../pages/Pages/Signup'
import Image from 'next/image'
const CoinSearch = () => {
const [coins, setCoins] = useState([])
const [coin, setCoin] = useState({})
const [name, setName] = useState("Name..")
const [search, setSearch] = useState("")
const [savedCoin, setSavedCoin] = useState(false)
function sendProps() {
console.log('coin: ', coin)
Router.push({
pathname: "/Pages/CoinInfo",
query: {
name,
coin
}
})
}
const saveCoin = async () => {
if (user?.email) {
setSavedCoin(true);
await updateDoc(coinPath, {
watchList: arrayUnion({
id: coin.id,
name: coin.name,
image: coin.image,
rank: coin.market_cap_rank,
symbol: coin.symbol,
}),
});
} else {
alert('Please sign in to save a coin to your watch list');
}
};
const coinGeckoUrl = 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=true&price_change_percentage=1h%2C%2024h%2C%207d'
const fetchCoins = async () => {
const data = await fetch(coinGeckoUrl)
const coins = await data.json()
setCoins(coins)
}
useEffect(() => {
fetchCoins()
}, [coinGeckoUrl])
return (
<div className="bg-white rounded-lg shadow-lg xl:px-32 lg:px-16 border py-10 ">
<div className="flex flex-col border border-gray-500/20 rounded-lg">
<h2 className="text-center font-semibold text-2xl py-2" >Search Crypto</h2>
<div className="px-4 py-2">
<input
onChange={(e) => setSearch(e.target.value)}
type="text"
placeholder="Search a Coin"
className="bg-gray-100 rounded-lg px-4 w-full shadow-lg py-2 text-lg border border-gray-300 outline-none"
/>
</div>
<div className="py-4 mx-4">
<table className="w-full border-collapse text-center ">
<thead className="">
<tr className='border-b'>
<th></th>
<th className='px-4'>#</th>
<th className='text-left'>Coin</th>
<th></th>
<th>Price</th>
<th>24h</th>
<th className='hidden md:table-cell'>24h Volume</th>
<th className='hidden sm:table-cell'>Mkt</th>
<th>Last 7 Days</th>
</tr>
</thead>
<tbody className="">
{
coins.filter((coin) => {
if(search === ""){
return coin
}
else {
return coin.name.toLowerCase().includes(search.toLowerCase())
}
}).map((coin, id) => (
<tr className='h-[80px] border-b overflow-hidden hover:scale-95 duration-300 cursor-pointer '>
<td onClick={saveCoin}>
{savedCoin ? <AiFillStar size={18} /> : <AiOutlineStar size={18} />}
</td>
<td>{coin.market_cap_rank}</td>
<td>
<div onClick={() => {
setCoin(coin)
sendProps()
}} className='flex items-center'>
<div>
<img
onClick={() => setSavedCoin(!savedCoin)}
className='w-6 mr-2 rounded-full'
src={coin.image}
alt={coin.id}
/>
</div>
<p className='hidden sm:table-cell'>{coin.name} <span className="text-gray-500 px-1 uppercase">{coin.symbol}</span></p>
</div>
</td>
<td></td>
<td>${coin.current_price.toLocaleString()}</td>
<td>
{coin.price_change_percentage_24h > 0 ? (
<p className='text-green-600'>
{coin.price_change_percentage_24h.toFixed(2)}%
</p>
) : (
<p className='text-red-600'>
{coin.price_change_percentage_24h.toFixed(2)}%
</p>
)}
</td>
<td className='w-[180px] hidden md:table-cell'>
${coin.total_volume.toLocaleString()}
</td>
<td className='w-[180px] hidden sm:table-cell'>
${coin.market_cap.toLocaleString()}
</td>
<td>
<Sparklines data={coin.sparkline_in_7d.price}>
{
coin.sparkline_in_7d.price[0] > coin.sparkline_in_7d.price[coin.sparkline_in_7d.price.length-1]
?
<SparklinesLine color='red' />
:
<SparklinesLine color='teal' />
}
</Sparklines>
</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
</div>
)
}
export default CoinSearch
CoinInfo.jsx
import React, { useEffect } from 'react'
import Footer from '../../components/Footer'
import Navbar from '../../components/Navbar'
import { Sparklines, SparklinesLine } from 'react-sparklines';
import { useRouter } from 'next/router'
const CoinInfo = () => {
const router = useRouter()
const {
query: { name, coin },
} = router
const props = {
name,
coin,
};
return (
<div className="w-full h-screen text-black bg-stone-200 px-6">
<Navbar />
<div className="bg-white rounded-lg shadow-lg xl:px-32 lg:px-16 border mt-8 px-6 pt-6 pb-10">
<h1>{props.name}</h1>
<h1>{props.coin.name}</h1>
</div>
<Footer />
</div>
)
}
export default CoinInfo
index.js
import { Inter } from '#next/font/google'
import styles from '../styles/Home.module.css'
import Navbar from '../components/Navbar'
import CoinSearch from '../components/CoinSearch'
import Trending from '../components/Trending'
import AboutUs from '../components/AboutUs'
import Footer from '../components/Footer'
import { AuthContextProvider } from '../context/AuthContext'
import Signup from './Pages/Signup'
const inter = Inter({ subsets: ['latin'] })
export default function Home() {
return (
<div className="w-full h-full text-black bg-stone-200 px-6">
<AuthContextProvider >
<Navbar />
<CoinSearch />
<Trending />
<AboutUs />
<Footer />
</AuthContextProvider>
</div>
)
}
File Structure

How to return multiple function in react in JSX format

I'm trying to return a few functions in react but I'm unable to perform as I wanted.
return (
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
)
}
I want to return my functions as above but when try this my app directly calls the last function performRedirect(). I don't know whether am I running this correctly or not.
please find the whole code below.
import React, { useState } from "react";
import { Link, Navigate } from "react-router-dom";
import {signin, authenticate, isAutheticated} from "../auth/helper/index"
const Login = () => {
const [values, setValues] = useState({
username: "",
password: "",
error: "",
loading: false,
didRedirect: false,
});
const {username, password, error, loading, didRedirect} = values;
const {user} = isAutheticated();
const handleChange = name => event => {
setValues({ ...values, error: false, [name]: event.target.value });
};
const onSubmit = event => {
event.preventDefault();
setValues({ ...values, error: false, loading: true });
signin({ username, password })
.then(data => {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
authenticate(data, () => {
setValues({
...values,
didRedirect: true
});
});
}
})
.catch(console.log("signin request failed", error, user));
};
const performRedirect = () => {
//TODO: do a redirect here
if (didRedirect) {
if (user && user.role === 1) {
return <p>redirect to admin</p>;
} else {
return <p>redirect to user dashboard</p>;
}
}
if (isAutheticated()) {
return <Navigate to="/" />;
}
};
const loadingMessage = () => {
return (
loading && (
<div className="alert alert-info">
<h2>Loading...</h2>
</div>
)
);
};
const errorMessage = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
</div>
</div>
);
};
const loginForm = () => {
return (
<div className='bg-gray-200'>
<div className="flex items-center h-screen w-full">
<div className="w-80 bg-white rounded-2xl p-6 m-0 md:max-w-sm md:mx-auto border border-slate-300 shadow-sm">
<div align='center' className='mt-3 mb-3 items-center content-center'> <img src={require('./../data/logo.jpg')} width="120px"/></div>
<span className="block w-full text-xl uppercase font-bold mb-4 text-center">Sign in to EMS
</span>
<form className="mb-0" action="/" method="post">
<div className="mb-4 md:w-full">
<label for="email" className="block text-xs mb-1 text-left text-gray-500">Username</label>
<input onChange={handleChange("username")} className="bg-gray-100 w-full border rounded-2xl px-4 py-2 outline-none focus:shadow-outline text-left text-xs" type="text" name="username" id="username" placeholder="Username" value={username}/>
</div>
<div className="mb-6 md:w-full relative">
<div className='flex w-full'>
<label for="password" className="block text-xs mb-1 text-center text-gray-500">Password</label>
<a className="text-xs text-right text-[#58a6ff] absolute right-0" href="/login">Forgot password?</a></div>
<input onChange={handleChange("password")} className="bg-gray-100 w-full border rounded-2xl px-4 py-2 outline-none focus:shadow-outline text-left text-xs" type="password" name="password" id="password" placeholder="Password" value={password}/>
</div>
<div className="mb-6 md:w-full relative">
<div className='flex w-full'>
<p className="block text-xs mb-1 text-center text-gray-500">{JSON.stringify(values)}</p>
</div>
<button className="bg-green-500 hover:bg-green-700 shadow-lg text-white uppercase text-sm font-semibold px-4 py-2 rounded-2xl text-center items-center w-full" onClick={onSubmit}>Login</button>
</form>
</div>
</div>
</div>
);
};
return (
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
)
}
export default Login
Please someone help me on this?
You can modify your return statement with an array value [] like below
return [
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
]
Another way, you can render those JSX functions by {} and wrap them into <React.Fragment></React.Fragment> (Or simpler version <></>)
return (
<React.Fragment>
{loadingMessage()}
{errorMessage()}
{loginForm()}
{performRedirect()}
</React.Fragment>)
like this:
return (
<>
{loadingMessage()}
{errorMessage()}
{loginForm()}
{performRedirect()}
</>
)

Google OAuth not directing to home page in react

I am setting up a login page using google OAuth in react, I am following a youtube tutorial, everything seems to work fine but somehow after logging in, I am not being redirected to my homepage. here is the code (Login.jsx):
import React from 'react'
import GoogleLogin from 'react-google-login';
import { useNavigate } from 'react-router-dom';
import { FcGoogle } from 'react-icons/fc';
import carVideo from '../assets/car.mp4';
import logo from '../assets/speedograph white.png';
import { client } from '../client';
const Login = () => {
const navigate = useNavigate();
const responseGoogle = (response) => {
localStorage.setItem('user', JSON.stringify(response.profileObj));
if (response.profileObj) {
const { name, googleId, imageUrl } = response.profileObj;
const doc = {
_id: googleId,
_type: 'user',
userName: name,
image: imageUrl,
};
client.createIfNotExists(doc).then(() => {
navigate('/', { replace: true });
});
}
};
return (
<div className = "flex justify-start items-center flex-col h-screen">
<div className='relative w-full h-full'>
<video
src={carVideo}
type='video/mp4'
loop
controls={false}
muted
autoPlay
className='w-full h-full object-cover'
/>
<div className = "absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackOverlay">
<div className="p-5 ml-3">
<img src={logo} width="130px" alt="logo" />
</div>
<div className='shadow-2xl'>
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
render={(renderProps) => (
<button
type='button'
className='bg-white flex justify-center items-center p-3 rounded-lg cursor-pointer outline-none'
onClick={renderProps.onClick}
disabled={renderProps.disabled}
>
<FcGoogle className='mr-4' />Sign in with Google
</button>
)}
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy="single_host_origin"
/>
</div>
</div>
</div>
</div>
)
}
export default Login
I think the problem is due to the if condition, but I added it after reviewing a Stackoverflow tab that suggested adding it as a null check, before adding it I was getting the error:
Cannot destructure property 'name' of 'response.profileObj'
now the error is gone but it is not redirecting me to the home page (neither did it do so before the error). So where am I missing in my code exactly?

Categories