I cannot clear input on submitting form - reactjs

I am using reactJs coupled with redux-form.
And also using the semantic ui react library
When i want to submit my form, i don't want my page to be refreshed. Instead i want to reset my form after the submission.
Unfortunately, i can't clear my input whereas i set the state to void the value.
/** Form component **/
<Form onSubmit={handleSubmit(this.handleSubmitAction)}>
<Field name="input" component={renderTitleInput} onChangeAction={this.handleInputChange} defaultValue={this.state.input} />
<input type="submit" name="submit" />
</Form>
/** HandleSubmit function **/
handleSubmitAction = (e) => {
this.setState({input:''})
}
The field remain filled after submitting the form.
Any suggestion ? thanks

What you created is an uncontrolled component, which means that update must be handled through the DOM. To do that you need to add the refattribute to get access to the DOM element in the form submit callback. Here is the changes you need to make.
<Form onSubmit={handleSubmit(this.handleSubmitAction)}>
<Field name="input" component={renderTitleInput} onChangeAction={this.handleInputChange} defaultValue={this.state.input} ref={(input) => this.input = input} />
<input type="submit" name="submit" />
</Form>
/** HandleSubmit function **/
handleSubmitAction = (e) => {
// This can be used when using controlled component.
//this.setState({input:''})
this.input.val = '';
}
But maybe what you want is to handle it as controlled component.

I had a similar issue and I want to clear input after submit button is clicked & use the functional component. here is an example of how I reset the value of input field after submitting.
Set value of the input to state value & when state value is reset input field get reset and the field is empty.
const [cancelInput, setCancelInput] = useState('');
const inputChange = (event, data) => {
// console.log(data)
setCancelInput(data.value)
}
const handleClick = (e) => {
setCancelInput(e.target.value)
}
<Input onChange={inputChange} placeholder='Type cancel here' value={cancelInput}/>
<Button color='red' onClick={handleClick} disabled={cancelInput !== 'cancel'} loading={loading} >Cancel</Button>

Related

How can I collect data by sending the register as props to the child component using React Hook Form?

Using React Hook Form, when I want to collect data by sending register as props to child component to take input value from child component, it shows 'register is not a function' error.
How can I solve this?
const { register, formState: { errors }, handleSubmit } = useForm();
const onSubmit = (data) => console.log(data);
<form onSubmit={handleSubmit(onSubmit)}>
<fieldset>
<legend className='text-[#666666]' >Status</legend>
{
statusData.map(status => <CheckboxFilter register={register} key={status._id} status={status}/>)
}
</fieldset>
</form>
here child
//CheckboxFilter component
const CheckboxFilter = ({ status, register }) => {
return (
<>
<p className='text-[#858585] mt-2 text-[14px]' >
<label htmlFor={status?.name} className='cursor-pointer' >
<input {...register("checkBoxData")} type="checkbox" name="status" id={status?.name} value={"status?.name"} /> {status?.name}
</label>
</p>
</>
);
};
I created a sandbox here codesandbox and it works perfectly.
I took your code and only changed the CheckboxFilter component:
Removed the name property (register function returns the name of the input based in the string you pass to it as a parameter, you should not override it)
Removed the value property (that was making the value of the checkbox constant, because there wasn't onChange handler that was modifying it)
Changed ...register("checkBoxData") to ...register(checkBoxData${name}) so this way you can have every checkbox value individually in the form.
Anyway, if you want to have a different behaviour than what I have assumed, let me know and I will help.
-Ado

React form handeling?

When using forms or input tags in react I use useState for the value of the form.
const [value,setvalue]=useState("");
onInput(e)=>{setvalue(e.target.value)};
But with this each time the user fills the form the component gets rerendered. Is there any better way to do that?
if you are using a form you can use onSubmit
<form onSubmit={this.handleSubmit}>
<input type="text" name="input1" />
<button type="submit">Submit</button>
</form>
and in handleSubmit function:
handleSubmit(event) {
event.preventDefault();
var input1 = event.currentTarget.input1.value;
// Do the rest
}

(Using React) Why is the submit button when onClick is performed using onChange events and resulting in empty string? (useState question)

Description:
The submit button calls a function called displayFields. This function then console logs the state of the input fields. The start of the input fields is listened to by onChange that sets the new state.
Before clicking the submit button the input fields when something is entered console logs the current state of the fields and then provides each string character in the console. To my understanding onChange should listen for changes but not console anything. When the button is clicked it should perform the function one time and console the current state of what is entered in fields. Instead when clicked the fields clear and then console an empty string.
I will provide my code and screen shots to help.
const GetQuote = (props) => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [question, setQuestion] = useState("");
const dispFields = () => {
console.log(name + email + question);
};
/*
This is used in case prevent defualt needs used
function handleSubmit(e) {
e.preventDefault(); }
*/
return (
<React.Fragment>
<form
id="quoteForm"
//onSubmit={handleSubmit}
>
<h1 id="quoteTitle"> Quote Help Form </h1>
<p id="quotePar">
{" "}
Please provide your Name, Contact Email, and what products you would
like more information about in this form:{" "}
</p>
<label id="formName" className="Form">
Name:
<input
type="text"
name="name"
onChange={(event) => {
setName(event.target.value);
}}
/>
</label>
<label id="formEmail" className="Form">
Email:
<input
type="text"
name="email"
onChange={(event) => {
setEmail(event.target.value);
}}
/>
</label>
<br />
<label id="formQuestion" className="Form">
What products would you like to know more about:
<input
type="text"
name="help"
onChange={(event) => {
setQuestion(event.target.value);
}}
/>{" "}
</label>
<br />
<br />
<button
id="quoteSubmit"
type="submit"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick={dispFields()}
>
Submit{" "}
</button>
</form>
</React.Fragment>
);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
onClick={dispFields()} is getting called on every render. If you pass it without calling it (onClick={dispFields} that should only log it to the console when the button is clicked.
You try to alter from
<
button id = "quoteSubmit"
type = "submit"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick = {
dispFields()
} >
Submit < /button>
to
<
button id = "quoteSubmit"
type = "button"
//funtion is called however seems to constantly call the useState which is used in onchange
//when submit is done returns empty string
onClick = {()=>
dispFields()
} >
Submit < /button>
Changed "button" from "submit", arrow function involved
Both solutions provided above work. Changing to example = {example} from example = {example()}. Also calling it from a arrow function also works. The issue is a node issue. What happens when the use breakpoints is set on the function, the values are console logged however after they are console logged the form refreshes and then the state refreshes so the console logs are never logged because the browser processes the value of event and clears the event at the same time. So as long as the values can be passed to the backend, the front end can remain clearing the value being rendered.

How to access state from components to the parent component

I have a form in which all input, select tags are separate components and each component but the submit button is in the form it self like-
<form>
<InputComp1 />
<InputComp2 />
<Select1 />
<Select2 />
<button type='submit' value='Register'/>
</form>
So how do I collect all state from various components and when user clicks on the submit the values get submitted.?
Is this approach while dealing with forms right? or should I manage state of all tags in the same component?
Manage the state of all inputs/selects in this component. You can pass values and handler functions to the inputs using props.
There is no "right" approach, the answer depends on the context.
You can have form as a controlled component, where you manage the state of all tags (while passing callbacks down the tree) as you suggested and as mentioned in docs.
Or, you can have it as uncontrolled component, for example:
const Input = ({ name }) => {
return <input name={name} />;
};
const Component = () => {
return (
<>
<form
onSubmit={(e) => {
e.preventDefault();
const data = new FormData(e.target);
const entries = data.entries();
for (let entry of entries) {
console.log(entry);
}
}}
>
<Input name="username" />
<Input name="email" />
<input type="submit" value="Submit" />
</form>
</>
);
};
See controlled vs uncontrolled components.
Yes you should manage the state in the parent component itself and pass the onchange handler and value of that field as props inside the child components to update the value of the form fields.
Solution #1 would be "manage state react way". With this you should store state you need to share between components somewhere in their common ancestor. In your case it would be component that holds Form
Solution #2 applicable only if you use real form and form controls. Handle 'submit' event from the form and get all you need to submit from form data.
Solution #3 applicable only if you use some sort of "state manager". Follow instructions and best practices of the library you use.
In some cases you can mix and match that solutions. For example I still recommend to handle 'submit' event on form regardless of solution.
there is a concept of state lifting in react:
create a controlled form here and for every child, component pass a function to get the data from child components to parent one. by doing this you can submit all the values once.
here is the example
import React, {useState} from 'react';
const ChildInput = ({onChange, id}) => {
return(
<input
key={id}
type="text"
placeholder="enter name"
onChange={onChange}
/>
)
}
const Parent = () => {
const [name, setName] = useState('');
const onSubmit =(e)=>{
e.preventDefault();
// append your all data here just like child component
data = {name}
}
return(
<form onSubmit={onSubbmit}>
<ChildInput onChange={()=>setName(e.target.value)} id="name" />
<button type="submit" value="submit"/>
</form>
)}
for more information check this one: https://reactjs.org/docs/glossary.html#controlled-vs-uncontrolled-components

Get value from textarea input in event object

I have a form with a textarea where users can put comments, and then trigger a onClick (when the form is submitet via the button).However, I cant get the value of the input, for example if a user writes "test", I want it to get into the handleSubmit function.
My form
<form onSubmit={this.handleSubmit.bind(this)} method="POST">
<label>Skicka</label>
<textarea placeholder="Type in comments (allergis etc.)" name ="name" ref ="name"></textarea>
<button className="btn" type="submit">
Send
</button>
</form>
//my handler
public handleSubmit = event => {
event.preventDefault();
console.log(event.name.value)
}
You have to save the textarea value separately in the onChange method of the textarea like this (for class component):
<form onSubmit={this.handleSubmit.bind(this)}
method="POST"
>
<label>Skicka</label>
<textarea
onChange={this.setComments}
placeholder="Type in comments (allergis etc.)"
name="name"
value={this.state.comment}/>
<button className="btn" type="submit">
Send
</button>
</form>
// The save function
const setComments = e => this.setState({comment: e.target.value});
This will save the textarea input in your local state and you can access it in your submit function with this.state.comment.
Hope this helps. Happy coding.
As you are using Uncontrolled Component. You can make use of ref to get value.
handleSubmit = (event) => {
event.preventDefault();
console.log(this.refs.name.value)
}
Demo
Note: In React you should never add method="POST" and action attribute's on form.
Don't add public keyword to your function (if you are not using typescript).
Better approach to work with form values, is Controlled Component
You can fix it by changing the handleSubmit method. Check below updated method.
public handleSubmit = event => {
event.preventDefault();
console.log(event.target.name.value)
}
But if you are work with React application then update the state variable via onChange event.

Resources