I am quite new to React JS and was trying to make an app. However whenever typing something in a textbook, the whole app seems to freeze and then stop working.
import React, { useState } from 'react'
import { auth } from './firebase';
import styles from '../static/SignIn.module.css';
import { Link, useNavigate } from "react-router-dom";
import {
// createUserWithEmailAndPassword,
signInWithEmailAndPassword,
onAuthStateChanged,
// signOut,
} from "firebase/auth";
export default function SignIn(){
const [user, setUser] = useState({});
const history = useNavigate();
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
// const goBack = () => {
// history.push('/')
// };
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const signIn = async() => {
try {
const user = await signInWithEmailAndPassword(
auth,
email,
password
);
history.push('/home')
console.log(user);
} catch (error) {
console.log(error)
if (password.length < 6){
alert('Password should be at least 6 characters!')
}
}
}
return(
<div className={styles.main}>
<div className={styles.center}>
<h1>Login</h1>
<div className={styles.form}>
<div className={styles.txt_field}>
<input type="text" id='text' name='text' value={email} onChange={e => setEmail(e.currentTarget.value)} required/>
<span></span>
<label>Email ID</label>
</div>
<div className={styles.txt_field}>
<input type="password" id='password' name='password' value={password} onChange={e => setPassword(e.currentTarget.value)} required/>
<span></span>
<label>Password</label>
</div>
<input type="submit" value="Login" onClick={signIn}/>
<div className={styles.signup_link}>
Not a member? <Link to="/signup">Signup</Link>
</div>
</div>
</div>
</div>
)
}
Any help would be appreciated because this is stopping me from progressing further, as I need to rerun the app using npm start in order to make it work.
I think your issue is that on every render of the SignIn component you call the onAuthStateChanged listener. I have never used this but my guess is that it would need to be called only once, when the component mounts.
So you could do something like this instead:
export default function SignIn(){
const [user, setUser] = useState({});
const history = useNavigate();
React.useEffect(() => {
onAuthStateChanged(auth, (currentUser) => setUser(currentUser))
// Notice the empty dependency array, there to make sure the effect is only run once when the component mounts
}, [])
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
// ...
}
I think everything is fine as I have tried running your code without the firebase functions and just removing the styles, just rendering the input button and it works fine and the events occur perfectly for setting email and password field. But I think you should make little amendments to your code. Please first check user object whether if it contains any data or not before pushing home route.
Related
This is the code i am working on
So, every time i make change to my input i want state to change which will change my url
but every time that happen it shows an error
Is there a alternative for onKeyPress beacuse it's not working and what change should i do to make that happen
"please read this code and tell me how to console log the JSON of my URL"
import React,{useState} from 'react';
import './App.css';
import axios from 'axios';
import Nav from "./components/Nav.js"
function App() {
const {data,setData} = useState({})
const {city,setCity} = useState('')
const url = `http://api.weatherapi.com/v1/current.json?key=e893692528f845dfad844704220412&q=${city}&aqi=yes`
function searchCity(event){
if(event.key === 'Enter') {
axios.get(url).then((response) => {
setData(response.data)
console.log(response.data)
})
}
}
return (
<div >
<Nav />
<div className='form'>
<input
value={city}
onChange={event => setCity(event.target.value)}
onKeyPress = {searchCity}
placeholder='Enter City'
type="text"
/>
</div>
<div className="Container">
<img src="./Img/top-japan-5.jpg" alt="Japan-as-weatherapp-top" className="main-img"/>
<div className="Temprature">12</div>
<div className="Location">Japan</div>
<div className="Weather">cloudy</div>
<div className="Humidity">Humidity</div>
<div className="line"></div>
<div className="Wind">Wind</div>
</div>
</div>
);
}
export default App;
the error massage
Uncaught TypeError: city is undefined
handleChange App.js:25
React 23
js index.js:5
factory react refresh:6
Webpack 3
useState should use [] not {}
const [data,setData] = useState({})
const [city,setCity] = useState('')
wrap the url around useMemo
const url = useMemo(() => `http://api.weatherapi.com/v1/current.json?key=e893692528f845dfad844704220412&q=${city}&aqi=yes`, [city])
Just off the first glimpse. Your useState is incorrect.
you have
const {data,setData} = useState({})
const {city,setCity} = useState('')
but you need
const [data, setData] = useState({});
const [city, setCity] = useState('');
Also, instead of onKeyPress on the input, I would use onSubmit on a form.
Do this...
import React, { useState } from 'react';
import './App.css';
import axios from 'axios';
import Nav from "./components/Nav.js"
function App() {
const [data, setData] = useState({})
const [city, setCity] = useState('')
function searchCity(event) {
event.preventDefault();
const url = `http://api.weatherapi.com/v1/current.json?key=e893692528f845dfad844704220412&q=${city}&aqi=yes`;
axios.get(url).then((response) => {
setData(response.data)
console.log(response.data)
})
}
return (
<div>
<Nav />
<form onSubmit={searchCity} className='form'>
<input
value={city}
onChange={event => setCity(event.target.value)}
placeholder='Enter City'
type="text"
/>
</form>
<div className="Container">
<img src="./Img/top-japan-5.jpg" alt="Japan-as-weatherapp-top" className="main-img"/>
<div className="Temprature">12</div>
<div className="Location">Japan</div>
<div className="Weather">cloudy</div>
<div className="Humidity">Humidity</div>
<div className="line"></div>
<div className="Wind">Wind</div>
</div>
</div>
);
}
export default App;
I think it would be better to call api in onChange and use event.target.value directly not setting state for it,
something like this :
function searchCity(cityToSearch) {
axios
.get(
`http://api.weatherapi.com/v1/current.json?key=e893692528f845dfad844704220412&q=${cityToSearch}&aqi=yes`
)
.then(response => {
setData(response.data);
console.log(response.data);
});
}
and in input :
<input
value={city}
onChange={event => {
setCity(event.target.value);
if (event.key === 'Enter') {
searchCity(event.target.value);
}
}}
placeholder="Enter City"
type="text"
/>
I'm in progress learning react and I have created an app with a login form. When the login form is submitted the login function passed to the component is executing twice as indicated in the console (logInUser – "running") even though the login button is only clicked once.
The function (loginUser) contains a promise blogService.setToken(xyz).then(xyz) and when the promise is removed the function only executes once.
While I have a method called setToken, this is not using a react state and so this shouldn't be contributing to the issue. I'm wondering why this the promise causing the component to re-render and if anyone could point me into the direction of documentation if promises cause a re-render. I can't seem to hit the right keywords to find the answer.
Can create a GitHub repo to share if that helps. Code below.
Cheers.
Console log
[Log] handleSubmit – "running"
[Log] handleSubmit – {token: "xxx", username: "xxx", name: "xxx"}
[Log] logInUser – "running"
[Log] logInUser: returnedObject – {token: "xxx", username: "xxx", name: "xxx"}
[Log] logInUser – "running"
App.js
import { useState, useEffect } from "react";
import blogService from "./services/blogs";
import LoginForm from "./components/Login";
//...
const App = () => {
const [user, setUser] = useState(null);
const logInUser = (returnedObj) => {
console.log("logInUser", "running");
if (returnedObj) {
console.log("logInUser: returnedObject", returnedObj);
// Causing a rerender
blogService.setToken(returnedObj.token)
.then(() => {
console.log('hello')
// then go and set the user
});
}
};
//...
return (
<div>
{user === null ? (
<div>
<h1>Login</h1>
<Notification message={notificationMessage} />
<LoginForm loggedInUser={logInUser} />
</div>
) : (
<div>
<h1>Logged in</h1>
</div>
)
components/Login.js
import { useState } from "react";
import loginService from "../services/login";
const LoginForm = ({ loggedInUser }) => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = async (event) => {
event.preventDefault();
console.clear();
const user = await loginService
.login({
username,
password,
})
.then((returnedUser) => {
console.log("handleSubmit", "running");
console.log("handleSubmit", returnedUser);
setUsername("");
setPassword("");
loggedInUser(returnedUser);
})
.catch(() => loggedInUser(null));
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Username</label>
<input
type="text"
name="Username"
value={username}
onChange={({ target }) => setUsername(target.value)}
/>
</div>
<div>
<label>Password</label>
<input
type="text"
name="Password"
value={password}
onChange={({ target }) => setPassword(target.value)}
/>
</div>
<button type="submit">Login</button>
</form>
);
};
export default LoginForm;
services/login.js
import axios from 'axios'
const baseUrl = '/api/login'
const login = async credentials => {
const response = await axios.post(baseUrl, credentials)
return response.data
}
export default { login }
service/blog.js
let token = null;
const setToken = (newToken) => {
token = `bearer ${newToken}`;
};
export default { setToken };
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { Button } from 'react-bootstrap';
import NavBarManu from './NavBarManu'
const Login = () => {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
function login() {
fetch("http://localhost:3000/login?q=" + name).then((data) => {
data.json().then((resp) => {
console.warn("resp", resp)
if (resp.length > 0) {
localStorage.setItem('login', JSON.stringify(resp))
//Facing error
console.warn(this.props.history.push('list'))
}
else {
alert("Please check username and password")
}
})
})
}
return (
<div>
<br /><h2>Please Login !</h2><br />
<input type="text"
placeholder="enter name"
name="user" onChange={(event) => setName(event.target.value)} /> <br /> <br />
<input
placeholder="enter password"
type="password" name="password" onChange={(event) => setPassword(event.target.value)} /> <br /> <br />
<button onClick={() => { login() }} >Login</button>
</div>
);
};
export default Login;
I am facing error in console.warn(this.props.history.push('list')).
The syntax is for class component. That's why it is showing error. I am facing some difficulty in implementing it in functional components.
After the user press login button i want the page to be directed towards "list" page.
Please someone can point out my error or If there is any other better way to approach this then do advice me .
You are creating functional component and using class component syntax. Your props are empty.
this key word is used in class components to reference to state.
It should be like this:
console.warn(history.push('list'))
You have to import:
import { useHistory } from "react-router-dom";
And in Login component body:
import { useHistory } from "react-router-dom";
const Login = () => {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const history = useHistory()
function login() {
fetch("http://localhost:3000/login?q=" + name).then((data) => {
data.json().then((resp) => {
console.warn("resp", resp)
if (resp.length > 0) {
localStorage.setItem('login', JSON.stringify(resp))
//Facing error
console.warn(history.push('list'))
}
else {
alert("Please check username and password")
}
})
})
}
return ...
I'm trying to make a little login screen with functional React. I have an input button that I want to click and have the login post happen. For the life of me, I can't get the handler to fire. loginPressed just won't get called. I'm sure it's something easy that I'm overlooking.
import * as React from 'react';
import axios from 'axios'
export default function Login() {
const [email, setEmail] = React.useState([]);
const [password, setPassword] = React.useState([]);
const loginPressed = () => {
var body = {
'email': email,
'password': password
}
axios.post('login', body)
.then(response => {
})
}
return (
<div>
<p>Username:</p>
<p><input type="text" name="email" onChange={(e) => {setEmail(e.target.value)}}/></p>
<p>Password:</p>
<p><input type="password" name="password" onChange={(e) => {setPassword(e.target.value)}}/></p>
<p>
<input type='button' value='Login' onClick={loginPressed}/>
</p>
</div>
);
}
You should use form with onSubmit={loginPressed}. Instead of input use button html element with type of submit.
I'm kinda new in programming and I'm learning how the web works, And Im working on this project using Supabase PostgreeSQL with Api, so what I want to do is write (send data to db), and I want to do it using only ReactJS but I don't know if this is possible, I have made something to work only with JS and the API keyes from SUPABASE, but I don't know if this is correct to do
import {useState} from 'react'
import {supabase} from '../db/supabase';
import Helmet from "helmet";
import {Link} from 'react-router-dom'
import styled from "styled-components";
const Container = styled.div``
const LeftContainer = styled.div``
const RightContainer = styled.div``
const Input = styled.input``
const BtnButBlack = styled.button``
const BtnButGreen = styled.button``
const Form = styled.form``
export default function Signup() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const handleSubmit = (event) => {
new_account({email: email, password: password}, name, username)
event.preventDefault();
};
const handleEmail = (event) => {
event.preventDefault();
setEmail(event.target.value)
};
const handlePassword = (event) => {
event.preventDefault();
setPassword(event.target.value)
}
const handleName = (event) => {
event.preventDefault();
setName(event.target.value)
}
const handleUsername = (event) => {
event.preventDefault();
setUsername(event.target.value)
}
const new_account = async ({email, password}) => {
const {user, session, error} = await supabase.auth.signUp({
email: email,
password: password,
})
if (error) {
console.error(error)
return
}
console.log(user);
await supabase
.from('Users')
.insert([
{username: username, name: name, email: email, password: password}
])
};
return (
<Container>
<LeftContainer>
Signup
</LeftContainer>
<RightContainer>
<Form onSubmit={handleSubmit}>
<Input onChange={handleUsername} type="text" value={username} placeholder="Username" autoComplete="false" /><br></br>
<Input onChange={handleName} type="text" value={name} placeholder="Name" autoComplete="false" /><br></br>
<Input onChange={handleEmail} type="text" value={email} placeholder="Email" autoComplete="false" /><br></br>
<Input onChange={handlePassword} type="password" value={password} placeholder="Password" autoComplete="false" /><br />
<BtnButGreen>Sign Up</BtnButGreen>
</Form>
</RightContainer>
</Container>
)
}
and this is the supabase module that you can import and use it on the jsx file:
import {createClient} from '#supabase/supabase-js'
const supabaseUrl = process.env.REACT_APP_SUPABASE_URL
const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
The code you have seems great! With Supabase, the you are only exposing anon key and supabase URL, which are meant to be public.
You use row level security and Supabase Auth to prevent malicious attackers to hack your database. You can read more about row level security here:
https://supabase.io/docs/learn/auth-deep-dive/auth-row-level-security
If you have any questions, please don't hesitate to ask!