Why is my handleChange method being rejected by React? - reactjs

I am trying to do a simple form task to try and learn React Forms but I am having a hard time understanding the syntax of it.
When I try the following code it works no problem:
import React, { useState } from "react";
function InputForm() {
const [emailValue, setEmailValue] = useState("");
console.log(emailValue);
return (
<>
<form>
<label>
Email:
<input
type="text"
name="input"
value={emailValue}
placeholder="type your email"
onChange={(e) => setEmailValue(e.target.value)}
/>
</label>
<br />
<br />
<button type="submit" name="test">
Submit Email
</button>
</form>
</>
);
}
export default InputForm;
However, when I try to clean it up so that there is not logic within the return, I get an error when I define my handleChange method.
import React, { useState } from "react";
function InputForm() {
const [emailValue, setEmailValue] = useState("");
handleChange(e) {
const { name, value } = e.target;
setEmailValue({ [name]: value });
};
console.log(emailValue);
return (
<>
<form>
<label>
Email:
<input
type="text"
name="input"
value={emailValue}
placeholder="type your email"
onChange={handleChange}
/>
</label>
<br />
<br />
<button type="submit" name="test">
Submit Email
</button>
</form>
</>
);
}
export default InputForm;
Can someone please explain why doing it this way doesn't work? The error I'm getting is that React is not expecting the { bracket after handleChange(e)... so the console error messages are useless in trying to figure out why it's not accepting it.
Thanks!

It's not React rejecting anything, it's just that, well, that's not correct JavaScript syntax.
You'll want
function InputForm() {
const [emailValue, setEmailValue] = useState("");
const handleChange = (e) {
const { name, value } = e.target;
setEmailValue({ [name]: value });
};
// ...
(and even so you're mixing and matching state types -- you have a state atom that's ostensibly a string (since you initialize it with a "") and then you assign an object into it... You may be looking for setEmailValue(value); there.)

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>
);
})}
</>
);
};

I wrote code in React Js, but in localhost it shows error, IDK where is the problem

I wrote this code, and when I want to use that in browser, it shows me parsing error.
import OnChange from 'react'
export default function OnChange() {
let formData = {};
let change = (e) => {
const { value, name } = e.target;
formData = { ...formData, [name]: value }
};
return (
<form
onSubmit={(e) => {
e.preventDefault();
alert(`${formData.lastName} ${formData.fName}`)
}}
>
<label htmlFor="lastName">Last name</label>
<input
type="text"
onChange={change}
id="lastName"
name="lastName"
value={formData.lastName}
/>
<input
type="text"
onChange={change}
id="lastName"
name="fName"
value={formData.fName}
/>
<button type='submit'>efgrf</button>
</form>
)
}
error:
Parsing error: Identifier 'OnChange' has already been declared
You imported OnChange as the default react import and then named your component the same. Just change the import of react to be correct.
import React from 'react';

Why does react turn my state into [object object]

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>
</>
);
}

'Input' is not defined react/jsx-no-undef, what does that mean?

Im trying to make an input field for name in my code, and I get:
'Input' is not defined react/jsx-no-undef and I cant see whats wrong, can anyone please help me?
I will later pass name into my dispatch
The form part with textarea is working.
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import '../styles/NewMessage.css'
import { fetchNewMessage } from 'reducer/messages'
export const NewMessage = () => {
const [message, setMessage] = useState('')
const [name, setName] = useState('')
const dispatch = useDispatch()
const handleMessageSubmit = (event) => {
event.preventDefault()
//console.log('addNewMessage', message)
dispatch(fetchNewMessage(message))
setMessage('')
}
return (
<div className="add-message-container">
{/* ******Form for sending a new message******* */}
<form onSubmit={handleMessageSubmit} className="add-message-form">
<span>
<label>
Name:
This input is giving me the 'Input' is not defined react/jsx-no-undef
<Input
placeholder="Name"
type="text"
onChange={event => setName(event.target.value)}
value={name}
required
/>
</label>
</span>
This textarea is working fine
<span>
<label For="new-message">
<textarea
id="new-message"
className="input-message"
rows='3'
minLength='5'
maxLength='150'
placeholder="Type your message"
onChange={(event) => setMessage(event.target.value)}
value={message}
required />
</label>
</span>
{/* * Form submit button * */}
<div className="add-message-btn-container">
<button
className="add-message-btn"
type="submit"
title="Send">
Send
</button>
</div>
</form>
</div>
)
}
You either need to import Input component from some component library or you need to use input which is the HTML element. JSX tags are case-sensitive, which is why it gives you are warning from eslint
<input
placeholder="Name"
type="text"
onChange={event => setName(event.target.value)}
value={name}
required
/>
it is <input> tag with small i.
Use <input /> instead of <Input />, as JSX attributes are case-sensitive

Adding a form to Gatsby JS, with an existing template that is export default

I am attempting to follow this tutorial to add a form to Gatsby JS. I understand it if my file wasn't setup differently. Firstly the tutorials component starts like this
export default class IndexPage extends React.Component {
Where I have this
export default ({ data }) => (
Then I am asked to place the following inside of it. I tried with both the render and return portion, and without.
state = {
firstName: "",
lastName: "",
}
handleInputChange = event => {
const target = event.target
const value = target.value
const name = target.name
this.setState({
[name]: value,
})
}
handleSubmit = event => {
event.preventDefault()
alert(`Welcome ${this.state.firstName} ${this.state.lastName}!`)
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
First name
<input
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.handleInputChange}
/>
</label>
<label>
Last name
<input
type="text"
name="lastName"
value={this.state.lastName}
onChange={this.handleInputChange}
/>
</label>
<button type="submit">Submit</button>
</form>
)
}
Here is all my code without the render and return portion
import React from 'react'
import { HelmetDatoCms } from 'gatsby-source-datocms'
import { graphql } from 'gatsby'
import Layout from "../components/layout"
export default ({ data }) => (
<Layout>
state = {
firstName: "",
lastName: "",
}
handleInputChange = event => {
const target = event.target
const value = target.value
const name = target.name
this.setState({
[name]: value,
})
}
handleSubmit = event => {
event.preventDefault()
alert(`Welcome ${this.state.firstName} ${this.state.lastName}!`)
}
<form onSubmit={this.handleSubmit}>
<label>
First name
<input
type="text"
name="firstName"
value={this.state.firstName}
onChange={this.handleInputChange}
/>
</label>
<label>
Last name
<input
type="text"
name="lastName"
value={this.state.lastName}
onChange={this.handleInputChange}
/>
</label>
<button type="submit">Submit</button>
</form>
<article className="sheet">
<HelmetDatoCms seo={data.datoCmsPricing.seoMetaTags} />
<section className="left-package-details">
<h1 className="sheet__title">{data.datoCmsPricing.title}</h1>
<p>
<span>${data.datoCmsPricing.priceAmount}</span> | <span>{data.datoCmsPricing.lengthOfSession}</span>
</p>
{data.datoCmsPricing.details.map(detailEntry => { return <li key={detailEntry.id}> {detailEntry.task}</li>})}
<p>
{data.datoCmsPricing.numberOfSessions}
</p>
book
<p>{data.datoCmsPricing.minimumMessage}</p>
</section>
<section className="right-package-details">
<img src={data.datoCmsPricing.coverImage.url} />
<div
className=""
dangerouslySetInnerHTML={{
__html: data.datoCmsPricing.descriptionNode.childMarkdownRemark.html,
}}
/>
</section>
</article>
</Layout>
)
export const query = graphql`
query WorkQuery($slug: String!) {
datoCmsPricing(slug: { eq: $slug }) {
seoMetaTags {
...GatsbyDatoCmsSeoMetaTags
}
title
priceAmount
details{
task
}
lengthOfSession
numberOfSessions
minimumMessage
descriptionNode {
childMarkdownRemark {
html
}
}
coverImage {
url
}
}
}
`
and the error I get is
There was a problem parsing "/mnt/c/Users/Anders/sites/jlfit-cms/src/templates/pricingDetails.js"; any GraphQL
fragments or queries in this file were not processed.
This may indicate a syntax error in the code, or it may be a file type
that Gatsby does not know how to parse.
File: /mnt/c/Users/Anders/sites/jlfit-cms/src/templates/pricingDetails.js
The problem you are facing is because you are trying to use state (and setState) on a functional component when the example uses a class.
Functional components don't have the same tools/syntax/APIs available to you as a class component (for better or worse) so you have to ensure you're using the correct approach for each case.
In the most recent versions of React you can have the equivalent of state and setState made available to you by using React hooks, more specifically the useState hook.
I've put together a quick working example of the code you pasted in your question converted to React hooks. You can find it on this sandbox.
I recommend you have a read over the initial parts of the React docs to ensure you're familiar with the foundational concepts or React, it will save a lot of headache in the future. 🙂

Resources