Estoy recibiendo este error:
Rechazo no controlado (TypeError): no se pueden leer las propiedades de undefined (leyendo 'valor')
Necesito obtener los valores del formulario de inicio de sesión (entradas: nombre de usuario y contraseña), pero cuando envío el formulario, aparece el error.
AuthContext.js
let loginUser = async (e) => { e.preventDefault(); let response = await fetch( "https://estudio-ghibli-2022.herokuapp.com/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username: e.target.username.value, password: e.target.password.value, }), } ); let data = await response.json(); console.log("data: ", data); }; let contextData = { loginUser: loginUser, };Esta es mi página de inicio de sesión:
const Login = () => { const { loginUser } = useContext(AuthContext); return ( <FormInner> <Title>Studio Ghibli Tracker</Title> <Subtitle>Login</Subtitle> <Container> <label>Email</label> <input name="username" placeholder="example@mail.com" /> <img src={userLogo} alt="user logo" /> </Container> <Container> <label>Password</label> <input name="password" placeholder="******" /> <img src={key} alt="key logo" /> </Container> <LoginBtn type="button" onClick={loginUser}> Login </LoginBtn> </FormInner> ); };Su función loginUser se adjunta al evento de clic <LoginBtn> . Suponiendo que el componente pasa algún tipo de Event al controlador, probablemente sea un evento activado por un <button> (o similar) que es lo que se asigna a e.target . No habrá ninguna propiedad de nombre de username .
Lo que debería estar haciendo aquí es que las entradas de su nombre de username y password sean componentes controlados con su valor vinculado al estado
const [username, setUsername] = useState(""); const [password, setPassword] = useState("");y
<input value={username} placeholder="example@mail.com" onChange={(e) => setUsername(e.target.value)} /> <input type="password" value={password} placeholder="******" onChange={(e) => setPassword(e.target.value)} /> Su función de contexto loginUser debe aceptar cadenas de nombre de username y password en lugar de un evento
const loginUser = async (username, password) => { const response = await fetch( "https://estudio-ghibli-2022.herokuapp.com/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ username, password }), } ); // don't forget to check for errors if (!response.ok) { throw response; } const data = await response.json(); console.log("loginUser data:", data); // now do something with data ¯\_(ツ)_/¯ };y
<LoginBtn type="button" onClick={(e) => { e.preventDefault(); loginUser(username, password); } >Login</LoginBtn>El problema es que está intentando acceder al valor de los campos de nombre de usuario y contraseña desde propiedades no existentes en su función loginUser :
body: JSON.stringify({ username: e.target.username.value, password: e.target.password.value, }) Supongo que el parámetro " e " es un React.MouseEvent porque está asignando loginUser como el controlador del evento onClick del componente <LoginBtn> :
<LoginBtn type="button" onClick={loginUser}> Login </LoginBtn> Entonces, a menos que tenga una implementación personalizada en ese componente que de alguna manera extraiga estos datos del formulario, existe una buena posibilidad de que e.target apunte a un elemento que no es relevante para que obtenga esta información.
Entonces, podría usar el enfoque sugerido por Phil en la otra respuesta usando componentes controlados para las entradas para solucionar el problema o también podría configurar su controlador en un evento onSubmit del formulario que contiene estos elementos y extraer la información usando FormData como este:
let loginUser = async (e) => { ... const formData = new FormData(e.target); const { username, password } = Object.fromEntries(formData.entries()); let response = await fetch(..., { ... body: JSON.stringify({ username, password }), ); ... }; Suponiendo que <FormInner> tiene el evento onSubmit :
<FormInner onSubmit={loginUser}>