Hello fellow devs
I am building a basic client in React to test some functionality of my API, admittedly my Node.js knowledge far surpasses my understanding of react, states and hooks.
The problem: I have 3 input fields, one for "username", one for "password" and one for "confirmPassword". Each of these inputs values update based of a "subscriber" useState hook. that I have set using a handleChange function with an onChange listener placed in each input.
I then have two buttons which rely on a separate use state hook called logOrReg to change based on if the user wants to login or register. This hook will adjust the function the submit button hits as well as the text in the submit button and the text in the the button used to switch to login or register.
On the first render when I launch the app the logOrReg state appears to be set correctly being submit button function: function postSub login-or-register button text: "Already have an account?" and Submit button text: "register".
When I start typing text into the inputs they update accordingly and so does the subscribers state via the handleChange function placed into each input. I then go to click the submit button, it then hits the postSub function but the the subscribers state does not get passed to the function and so the API receives blank values in its console and the subscriber.username and subscriber.password targets in the postSub function come out blank in a console.log on the client side.
However if I click "already have an account?" the buttons switch (with the text in the inputs staying the same) and then click "Don't have an account?" the buttons change back to the register state as expected. I then click "register" and the values from the subscriber state set in the inputs suddenly get passed over to the postSub function and the API receives the password and username and registers the new user.
Then if I try to update the values in the input fields again the updated values don't get passed to the postSub function but instead the values from the initial registration get passed to the function and subsequently the api returning a message on my API console stating that the user has already been registered.
When looking at my components and states in the React dev tolls in the google developer console they all appear to be updating correctly, so its super confusing that when I click submit the state of the inputs doesn't get passed to the function. My assumption is I am not understanding how the useState hooks work but if they are displaying correctly in the Dev tools I have no idea how to understand why the values are not being passed to the function.
I really hope this makes sense, its such a weird problem to describe.
The code:
import React, {useState, useEffect} from 'react'
import Pusher from 'pusher-js';
import axios from "axios";
import Table from '@mui/material/Table';
import TableHead from '@mui/material/TableHead';
import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
const PUSHER_APP_KEY = "b4173b2b1b29274b8621";
const PUSHER_APP_CLUSTER = "eu";
function Resthome(e) {
const pusher = new Pusher(PUSHER_APP_KEY, {cluster: PUSHER_APP_CLUSTER})
// var [activeOrders, setActiveOrders] = useState([])
// axios.get("hhttp://localhost:3000/restaurants/getactiveorders")
// .then(response => { setActiveOrders(response) })
// console.log(activeOrders) This will be called when your component is mounted
useEffect(() => {
const channel = pusher.subscribe("rests")
let mounted = true;
if (mounted) {
console.log("mounted")
channel.bind("inserted", (data) => {
console.log("inserted")
console.log("data", JSON.stringify(data))
alert("you have been subscribed")
})
}
return (() => {
pusher.unsubscribe("rests")
mounted = false
})
}, []);
// [] would ensure that useEffect is executed only once
function LoginOrRegister() {
const [subscriber,
setSubscriber] = useState({
username: "",
password: "",
confirmPassword: ""
})
const [logOrReg,
setLogOrReg] = useState({type: "reg", function: postSub, submitButton: "register", switchButton: "already have an account?"})
function handleChange(event) {
const newValue = event.target.value;
const inputName = event.target.name;
setSubscriber(prevValue => {
if (inputName === "username") {
return {username: newValue, password: prevValue.password, confirmPassword: prevValue.confirmPassword}
} else if (inputName === "password") {
return {username: prevValue.username, password: newValue, confirmPassword: prevValue.confirmPassword}
} else if (inputName === "confirmPassword") {
return {username: prevValue.username, password: prevValue.password, confirmPassword: newValue}
}
})
console.log("set sub username", subscriber.username, "set sub password", subscriber.password)
}
function Switch(e) {
e.preventDefault()
if (logOrReg.type === "reg") {
setLogOrReg({type: "log", function: logUser, submitButton: "login", switchButton: "Dont have an account?"})
} else if (logOrReg.type === "log") {
setLogOrReg({type: "reg", function: postSub, submitButton: "register", switchButton: "Already have an account?"})
}
}
async function postSub(e) {
e.preventDefault()
console.log("password", subscriber.password, "username", subscriber.username)
try {
if (subscriber.password === subscriber.confirmPassword) {
await axios
.post("http://localhost:3000/restaurants/register", {
username: subscriber.username,
password: subscriber.password
})
.then(response => {
if (response.status === 201) {
console.log("request sent successfully")
}
})
} else {
alert("Passwords dont match")
}
} catch (err) {
console.log(err)
}
}
async function logUser(e) {
e.preventDefault()
try {
if (subscriber.password === subscriber.confirmPassword) {
await axios
.post("http://localhost:3000/restaurants/login", {
username: subscriber.username,
password: subscriber.password
})
.then(response => {
if (response.status === 201) {
console.log("request sent successfully")
console.log(response)
}
})
} else {
alert("Passwords dont match")
}
} catch (err) {
console.log(err)
}
}
// var [logOrReg, setlogOrReg] = useState({username: "", password: "",
// confirmPassword: ""})
return (
<div>
<form onSubmit={logOrReg.function}>
<h1>Signup</h1>
<input
name="username"
onChange={handleChange}
placeholder="username"
value={subscriber.username}
label="email"></input>
<input
name="password"
onChange={handleChange}
placeholder="password"
value={subscriber.password}
label="password"></input>
<input
name="confirmPassword"
onChange={handleChange}
placeholder="confirmPassword"
value={subscriber.confirmPassword}
label="password"></input>
<button type="submit">
<h3>
{logOrReg.submitButton}
</h3>
</button>
</form>
<button name="login-or-register" onClick={Switch}>
<h3>{logOrReg.switchButton}</h3>
</button>
</div>
)
};
return (
<div>
<LoginOrRegister/>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell align="right">Total</TableCell>
<TableCell align="right">Item names</TableCell>
<TableCell align="right">Status</TableCell>
<TableCell align="right">Time Placed</TableCell>
</TableRow>
</TableHead>
</Table>
</div>
)
}
export default Resthome