Why does react turn my state into [object object] - reactjs

I've got this straightforward component:
Here it is on CodeSandbox: https://codesandbox.io/s/fast-architecture-fgvwg?fontsize=14&hidenavigation=1&theme=dark
function Home() {
const [name, setName] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(name);
};
return (
<>
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={setName}
type="text"
placeholder="name"
/>
<button type="submit">
submit
</button>
</form>
</>
);
}
export default Home;
As soon as I click in the input box, it turns into [object object] and I'd love to know why this is happening.

You are not passing a value to your name variable onChange. onChange returns event which you have to get the value from and set the name that way.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [name, setName] = useState("");
const handleSubmit = e => {
e.preventDefault();
console.log(name);
};
return (
<>
<form onSubmit={handleSubmit}>
<input value={name} onChange={(e) => setName(e.currentTarget.value)} type="text" placeholder="name" />
<button type="submit">submit</button>
</form>
</>
);
}
The update here is the onChange attribute. You are grabbing the event e and setting the name to whatever that currentTarget value is.
onChange = { (e) => setName(e.currentTarget.value) }

Your onChange handler receives a change event object. If you want the new value you'll need to get it from the event: event.target.value:
<input
value={name}
onChange={e => setName(e.target.value)}
type="text"
placeholder="name"
/>
When you cast a value to a string, like when calling console.log, the value's toString method is invoked, which for objects returns [object Object] by default.

You had onChange set to setName. Setname is a function used to update the value of name.
You need to write a function to handle the name value being updating when the user types in a name. Set onChange equal to that function:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [name, setName] = useState("");
const handleSubmit = e => {
e.preventDefault();
console.log(name);
};
function handleChange(e) {
e.preventDefault();
setName(e.target.value);
}
return (
<>
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={handleChange}
type="text"
placeholder="name"
/>
<button type="submit">submit</button>
</form>
</>
);
}

Related

Get id from one form out of multiple forms? (React)

I am trying send only one of my form's id to my handleSubmit function in react. My forms are created via a map function, which creates a form for each data enter from my DB. My handleSubmit function currently take in an event and outputs it to the console log. When running the code, I get all of my id's instead of one. Any help?
Here is my code:
import React, { useRef, useState } from 'react';
export const Movie = ({listOfReviews}) =>{
const handleSubmit = (event) => {
console.log(event)
}
return (
<>
<h1>Your reviews:</h1>
{listOfReviews.map(review =>{
return(
<form onSubmit={handleSubmit(review.id)}>
<label>
Movieid:{review.movieid}
<input type="text" value={review.id} readonly="readonly" ></input>
<input type="text" value={review.comment}></input>
<input type="submit" value="Delete"></input>
</label>
</form>
)
})}
</>
)
}
You have a simple error in your onSubmit callback. Instead of calling handleSubmit in the callback prop, you should instead define an inline function that calls handleSubmit.
Like this:
<form onSubmit={() => handleSubmit(review.id)}>
Full code:
import React, { useRef, useState } from 'react';
export const Movie = ({ listOfReviews }) => {
const handleSubmit = (id) => {
console.log(id);
};
return (
<>
<h1>Your reviews:</h1>
{listOfReviews.map((review) => {
return (
<form onSubmit={() => handleSubmit(review.id)}>
<label>
Movieid:{review.movieid}
<input type="text" value={review.id} readonly="readonly"></input>
<input type="text" value={review.comment}></input>
<input type="submit" value="Delete"></input>
</label>
</form>
);
})}
</>
);
};

Next js send form data to parent page

I create a simple page called lucky number
pages/lucky.js
import finder from '../../hooks/use-finder'
import NumberForm from '../components/number-form'
export default function LuckyNumber() {
const { data } = finder(number)
console.log(data)
return (
<>
<h1>Lucky Number</h1>
<NumberForm />
</>
)
}
export default function NumberForm() {
return (
<>
<form>
<label>
Number:
<input type="text" name="number" />
</label>
<input type="submit" value="Submit" />
</form>
</>
)
}
where NumberForm is a form where user can just input a number ex: 12345. Once use submits the form, I want to pass that number to my hook in the page finder(number) so I can check to see if that number is in my lucky list of numbers.
How can I pass the number that user submits to the page?
I think you can use parent state and send the setState to the child to update it i.e.
pages/lucky.js
import React, { useState } from 'react'
import finder from '../../hooks/use-finder'
import NumberForm from '../components/number-form'
export default function LuckyNumber() {
const [number, setnumber] = useState(0);
const { data } = finder(number)
console.log(data)
return (
<>
<h1>Lucky Number</h1>
<NumberForm onChange={setnumber} />
</>
)
}
export default function NumberForm({ onChange }) {
const [number, setnumber] = useState(0);
const handleChange = (event)=>{
setNumber(event?.target?.value)
}
const handleSubmit = (event)=>{
event.preventDefault();
onChange(number)
}
return (
<>
<form>
<label>
Number:
<input type="text" name="number" value={number} onChange={ handleChange } />
</label>
<input type="submit" value="Submit" onClick={ handleSubmit } />
</form>
</>
)
}

React Typescript input onChange event type?

I'm trying to get text from a input element, setting it to state and then rendering it back into the input box. However I think my event typing is wrong? I've searched online and tried implementing many solutions but none have worked so far. Any help is appreciated.
my component:
import React, { ChangeEvent, ChangeEventHandler, useState } from "react";
export default function Unidirectionflow() {
const [state4, setState4] = useState("");
const [state5, setState5] = useState("");
let handleChange4 = (e: React.FormEvent<HTMLInputElement>): void => {
setState3((e.target as HTMLInputElement).value);
};
let handleChange5 = (event: ChangeEvent<HTMLInputElement>) => {
setState5(event.currentTarget.value);
};
return (
<main>
<input type="text" value={state4} onChange={() => handleChange4} />
<input type="text" value={state5} onChange={() => handleChange5} />
</main>
);
}
Typescript input onchange event.target.value
React TypeScript: Correct Types for onChange
Can't type in React TextField Input
https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/
You can do like this
export default function Unidirectionflow() {
const [states, setStates] = useState({
state3:'',
state4:''
})
const handleChange = (
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setStates({
...states,
[e.target.name]: e.target.value.trim(),
});
};
return (
<main>
<input type="text" name="state3" value={states.state3} onChange={handleChange} />
<input type="text" name="state4" value={states.state4} onChange={handleChange} />
</main>
);
};
onChange={handleChange}
See if this can help you!
Just do this:
handleChange = (event: Event) => {
const { value } = event.target as unknown as { value: string };
setState(value);
};
<input type='text' onChange={handleChange} />
And the squeegee lines will go away.
You have forgot to pass the event when calling the function
Try this
onChange={(e) => handleChange(e)}
Or
onChange={handleChange}
Code sandbox => https://codesandbox.io/s/dreamy-pateu-1mc6j?file=/src/App.tsx

How to do validation using useRef()

How do I validate input box value using useRef .
Initial validation is not required once user clicks on input box and comes out then it should validate if input box is empty it should show input box cannot be empty.
Codesandbox Link
code i tried. using onBlur
export default function App() {
const name = React.useRef("");
const nameBlurData = (name) => {
console.log("name", name);
};
return (
<div className="App">
<form>
<input
onBlur={() => nameBlurData(name.current.value)}
type="text"
ref={name}
placeholder="Enter First Name"
/>
// show error message here
</form>
</div>
);
}
You can use "useRef" to validate the value of an input field.
No need to use "useState".
Below code is a basic implementation of OP's question
You can replace the "console.log" with your alert component.
import { useRef } from "react";
const ComponentA = () => {
const emailRef = useRef(null);
const passwordRef = useRef(null);
const onBlurHandler = (refInput) => {
if (refInput.current?.value === "") {
console.log(`${refInput.current.name} is empty!`);
}
}
return (
<form>
<input ref={emailRef} onBlur={onBlurHandler.bind(this, emailRef)} />
<input ref={passwordRef} onBlur={onBlurHandler.bind(this, passwordRef)} />
<form/>
)
}
Link to "useRef"
Note: Not tested, code typed directly to SO's RTE
You can use a local state and conditionally render an error message like this:
const [isValid, setIsValid] = useState(true)
const nameBlurData = (name) => {
setIsValid(!!name);
};
return (
<div className="App">
<form>
<input
onBlur={() => nameBlurData(name.current.value)}
type="text"
ref={name}
placeholder="Enter First Name"
/>
{!isValid && <span> input must not be empty </span> }
</form>
Note that you don't really need a ref in this case, you can just use the event object like:
onBlur={(event) => nameBlurData(event.target.value)}
You need to use useState hook to update the value of the name property. Using ref is not ideal here.
Live demo https://stackblitz.com/edit/react-apqj86?devtoolsheight=33&file=src/App.js
import React, { useState } from 'react';
export default function App() {
const [name, setName] = useState('');
const [hasError, setError] = useState(false);
const nameBlurData = () => {
if (name.trim() === '') {
setError(true);
return;
}
setError(false);
};
return (
<div className="App">
<form>
<input
onBlur={nameBlurData}
type="text"
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter First Name"
/>
{hasError ? <p style={{ color: 'red' }}>Name is required</p> : null}
</form>
</div>
);
}

React TypeScript: Alternatives to UseRef in functional components

Is there another way of getting/setting the values from the dom that is less expensive than useRef()? Is useRef() to be used lightly as the docs suggest?
import React, { useRef, useEffect } from 'react';
const Join: React.FC = () => {
const fullName = useRef<HTMLInputElement>(null);
const email = useRef<HTMLInputElement>(null);
const password = useRef<HTMLInputElement>(null);
const myForm = useRef<HTMLFormElement>(null);
useEffect(() => {
if (myForm.current) myForm.current.reset();
if (fullName.current) fullName.current.focus();
}, []);
return (
<div>
<form ref={myForm}>
<input type='text' ref={fullName} />
<input type='text' ref={email} />
<input type='text' ref={password} />
</form>
</div>
)
}
When the component loads I want to clear the form and focus the
fullName input
You don't need refs for that
I want to clear the form
Make your inputs controlled
Declare an empty string as initial value
const Component = () =>{
const [state, setState] = useState({
email : '',
password : ''
})
const onChange = ({ target: { value, name } }) =>{
setState(prev => ({
...prev,
[name] : value
}))
}
const { email, password } = state
return(
<>
<input value={email} onChange={onChange} id='email'/>
<input value={password} onChange={onChange} id='password' />
</>
)
}
Automatically focus a given input
Just use autofocus for that
<input autofocus/>

Resources