OnSubmit event not fired with preventDefault on the container - reactjs

Would somebody explain to me why the submit callback is not called when I try to submit the form (using the button or by pressing enter) ?
The reason is this onClick event on the container but I cannot grasp why...
Shouldn't the submit event be caught by the form before bubbling up to the div with onClick?
export default function App() {
const [val, setVal] = useState("");
function submit() {
alert(val);
}
function prevent(e) {
e.preventDefault();
}
return (
<div className="App" onClick={prevent}>
<form onSubmit={submit}>
<input
name="test"
value={val}
onChange={(e) => setVal(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
codesandbox
Edit:
My form is inside an 'a' tag and because of that, I wanted to use preventDefault so the user to not be redirected when filling up the form.
Thanks in advance!

I am not sure what you are trying to achieve here, but preventing default actions on the parent element is not actually the best thing to do. Your code could have been better this way:
export default function App() {
const [val, setVal] = useState("");
function submit(e) {
e.preventDefault();
alert(val);
}
return (
<form onSubmit={(e) => submit(e)}>
<input
name="test"
value={val}
onChange={(e) => setVal(e.target.value)}
/>
<button type="submit">Submit</button>
</form>);
}
The prevent() function is unnecessary and have no meaningful impacts on your code. Keeping it simple and sweet is the best way to go.

Related

Trigger "tick box" message in checkbox field

I am using React, and I would like to find a way to trigger this message (that now triggers only when pressing the type="submit" button, on will, is there any action I can use to trigger this message at any point (for example if a user presses any other button)
<input
id="conditions"
type="checkbox"
name="conditions"
ref={acceptConditions}
required
></input>
This can be achieved with reportValidity() MDN documentation
setTimeout(() =>
document.getElementById('example').reportValidity(),
3000
)
<input id="example" type="checkbox" required />
Ok here are a few approaches, that works.
approach 1
Using the reportValidity()
This function will check the validity of the element and then trigger the event.
import { useRef } from "react";
import "./styles.css";
export default function App() {
const acceptConditions = useRef();
const formRef = useRef();
const handleSubmit = () => {
acceptConditions.current.reportValidity();
};
return (
<form ref={formRef}>
<input
id="conditions"
type="checkbox"
name="conditions"
ref={acceptConditions}
required
></input>
<span>Tick this box to continue</span>
<br />
<button type={"submit"}>submit the form</button>
<br />
<button onClick={handleSubmit}>Imposter button</button>
</form>
);
}
This is a good apporach And one that i recommend.
approach 2:
First of all if you want any other button to trigger the same event then you can do is make a reference to the form and then submit the form manually on the button press.
Here is an example.
import { useRef } from "react";
import "./styles.css";
export default function App() {
const acceptConditions = useRef();
const formRef = useRef();
const handleSubmit = () => {
console.log(formRef.current.submit);
};
return (
<form ref={formRef}>
<input
id="conditions"
type="checkbox"
name="conditions"
ref={acceptConditions}
required
></input>
<span>Tick this box to continue</span>
<br />
<button type={"submit"}>submit the form</button>
<br />
<button onClick={handleSubmit}>Imposter button</button>
</form>
);
}
in the above code the imposter button will trigger the same action as the button with the type="submit".
thank you.

Prevent function from running when a variable changes in React

I have a form with a checkbox and text input.
const [formVars, setFormVars] = useState<any>({checkbox:true})
const submitForm = () => {
console.log({formVars})
}
render (
<Checkbox checked={formVars.checkbox} /> Bake the cookies?
<TextInput label="what kind of cookies?" />
<Button onClick={() => submitForm()}
)
submitForm should not run until the user clicks submit, however my code seems to be producing a never-ending loop where the form changes formVars, and the change sets off submitForm. How can I prevent this?
There are a bunch of typos in the question, so I created a simple copy of your code.
The button's onClick prop takes a callback, not a function call. You're likely calling the submit function instead of passing it to the button onClick prop.
Here's how you trigger the submission manually for controlled inputs
export default function App() {
const [formVars, setFormVars] = useState({ checkbox: true });
const submitForm = (e) => {
console.log({ formVars });
};
const handleChange = (e) => {
setFormVars(e.target.value);
};
return (
<>
<label>
Name:
<input onChange={handleChange} type="text" name="name" />
</label>
<button onClick={submitForm}>submit</button>
</>
);
}
<Button onClick={()=> submitForm}
Try this syntax for the button

Set item in onclick is not logging expected output

I'm writing a simple react code that adds a value to a list onClick of a button. and after adding, I'm logging it in the same block. Currently, my issue is, that the logging is happening with n-1 entered string. i.e. If I enter egg and then add milk, after adding milk, I see egg logged and so on. Here is my code.
function App() {
const [list, setList] = useState([]);
const [gItem, setGItem] = useState("");
const AddItem = (e) => {
e.preventDefault();
setList([...list, gItem]);
console.log(list);
};
return (
<>
<form className="grocery-form">
<h3>grocery bud</h3>
<div className="form-control">
<label htmlFor="name"></label>
<input
type="text"
placeholder="e.g. eggs"
className="grocery"
name="name"
id="name"
onChange={(e) => setGItem(e.target.value)}
/>
<button className="submit-btn" type="submit" onClick={AddItem}>
Submit
</button>
</div>
</form>
<div className="grocery-container">
<List items={list} />
</div>
</>
);
}
I'm unable to understand where I'm going wrong.
setList updates state asynchronously so if you log state after using it the previous value will be displayed, to make it log the current state after this list was changed you can use useEffect hook like this:
useEffect(() => {
console.log(list);
}, [list])

React - how to target value from a form with onClick

New to react and currently working on a project with a backend.
Everything functions correctly apart from targeting the value of user selection.
basically whenever a user enters a number the setId is saved properly to the const with no problems while using the onChange method.
this method would render my page every change on text.
I am trying to save the Id only when the user clicks the button. however,
event.target.value does not work with onClick.
I tried using event.currentTarget.value and this does not seem to work.
Code:
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input value={id} onChange={(e) => setId(e.target.value)} type="number" />
{/* <button value={id} type="button" onClick={(e) => setId(e.currentTarget.value)}>Search</button> */}
</form>
Handle Submit:
const handleSubmit = (e) => {
e.preventDefault();
console.log(id)
}
is there a way of doing this with onclick? since I wouldn't like my component to render on every typo and only once a user has clicked the button.
Componenet:
interface GetOneCompanyProps {
company: CompanyModel;
}
interface RouteParam {
id: any;
}
interface CompanyById extends RouteComponentProps<RouteParam> {
}
function GetOneCompany(): JSX.Element {
const [id, setId] = useState('4');
const [company, setCompany] = useState<any>('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(id)
}
async function send() {
try {
const response = await axios.get<CompanyModel>(globals.adminUrls.getOneCompany + id)
store.dispatch(oneCompanyAction(response.data));
console.log(response);
const company = response.data;
setCompany(company)
} catch (err) {
notify.error(err);
}
}
useEffect(() => {
send();
}, [id]);
return (
<div className="getOneCompany">
<h1>hi </h1>
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input value={id} onChange={(e) => setId(e.target.value)} type="number" />
{/* <button value={id} type="button" onClick={(e) => setId(e.currentTarget.value)}>Search</button> */}
</form>
<div className="top">
</div>
<br/>
Company: {id}
<br/>
Client Type: {company.clientType}
<br/>
Company Name: {company.name}
<br/>
Email Adress: {company.email}
<br/>
</div>
);
}
export default GetOneCompany;
Hope I am clear on this.
Thanks.
You can turn your input from being a controlled input to an uncontrolled input, and make use of the useRef hook. Basically, remove most of your attributes from the input element, and grab the current value of the input form on click of the button. From there, you can do whatever you want with the input value.
const inputRef = useRef()
...other code
<form onSubmit={handleSubmit}>
<label>Company ID</label>
<input type="number" ref={inputRef} />
<button value={id} type="button" onClick={() => console.log(inputRef.current.value)}>Search</button>
</form>
...other code
I'm afraid to say that here onChange is mandatory as we also are interested in the value which we set by setId. onClick can't be used as we can't set the value in the input.
Hope I'm clear.
Thankyou!

Get the values in the form, from a component outside the form

I've a component that is built using react-hook-form. I'm trying access the value in form, through a button that is sibling of the Form component. Basically the getvalue function should somehow get the values in the form.
Form.tsx
export default function Form({ onSubmit }) {
const { register, handleSubmit } = useForm({
defaultValues: {
firstName: "bill",
lastName: "luo",
email: "bluebill1049#hotmail.com"
}
});
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName")} />
<input {...register("lastName")} />
<input {...register("email")} />
<button type="submit">Submit</button>
</form>
)
}
App.tsx
const onSubmit = data => console.log(data);
const getValue = ???
function App() {
return (
<Form onSubmit={onSubmit}/>
<button onClick={getValue} />
)
}
I want to get the form data values in getValue
You could use onChange to set the values in the form
<Form onSubmit={onSubmit} geValue={getValue}/>
and inside the Form.tsx
<form onSubmit={handleSubmit(onSubmit)} onChange={handleChange(getValue)}>
however i'm not really sure if this would work for you - can you elaborate more about what you are trying to do, maybe we can help you better.
Also, you should only pass callbacks to onSubmit and onChange so probably this is the correct syntax for that
<form onSubmit={(e) => handleSubmit(e, onSubmit)} onChange={(e) => handleChange(e, getValue)}>

Resources