What is value={} for in React inputs?
I currently have a state of const [username, setUsername] = useState("");
and an input element in my form that updates whatever the user is typing in the input to the state.
<input type="text" value={username} name="Username" onChange={({target}) => setPassword(target.value)}/>
Why do i need to specify the value in the input? What is the purpose of having the value be the new state variable? It seems to work fine without the value={} at all if I remove it
Doing it with a value prop is called a "controlled component", and otherwise it's an "uncontrolled component". Both of these approaches are supported in react, but the controlled component gives you more... well... control. If you ever need to do something deviates from the built in behavior of the browser, then you must use a controlled component.
So for example, if you want to take what the user typed and make it upper case, you need a controlled component. If you want to have a button which clears the text of your inputs, you need a controlled component. The only case that works with uncontrolled components is if you want literally what the user types.
https://reactjs.org/docs/uncontrolled-components.html
Related
Hello:) I am writing simple application(similar to to-do-list). The task is to add such functionality as the ability to change the title of the announcement.
You add the title and description of the announcement and click on "submit" button -> https://prnt.sc/tf8zxl
the annoncement appears below and you need to have the ability to change the title of it(rename it)->https://prnt.sc/tf8xa2
I added the input when click on the title but it does not allow to write inside it and I do not have any ideas on how to save it in this.state.data correctly.
here is the source code -> https://codesandbox.io/s/eager-darkness-uh9xl?file=/src/App.js
Controlled input
If you need controlled input you have to change values somehow. You are not changing anything at this moment and you are calling handleChange which changes state.title, not state.data[someIndex].title - so the value cannot be changed.
I've provided modified solution where is updating finnished.
Uncontrolled input
If you are OK with uncontrolled input you are probably looking for input attribute defaultValue instead of value. It doesn't change because you are not changing value at all so it's being instantly re-rendered with original value from this.props.data.title.
I've set value by attribute defaultValue and changed onChange on onBlur so update will triger only when you lose focus.
Your modified codesandbox.
Use input in this way
const [title,setTitle] = useState('')
<input type="text" value={title} onChange={(e)=>setTitle(e.target.value)} />
I read the answers on this question but none is similar to my set up:
What are controlled components and uncontrolled components?
I have a parent component and many children as inputs. Each input has a defaultValue that is set using a prop received from the parent and the validation of the input is performed on onBlur. This is because the validation is asynchronous, so onChange would slow down the app like crazy.
How is this orchestration called? The traditional definition for "controlled" seems to be an input which updates on every onChange, while an "uncontrolled" input is one which manages its own internal state, which is later accessed via a ref. My set up seems to fall short of both, sitting somewhere in the middle - or not?
Update: Here's a CodeSandbox.
If I understand your setup correctly, your inputs are uncontrolled, because their state is held in the DOM rather than in React state. Validation is a separate concern, which can happen synchronously or asynchronously. You can let React state hold the values whatever you do for validation. Note that most of the time you don't want to prevent the input from even having an invalid value - you just want to ensure that the user can't submit the form while the values are invalid. Thus you can have an onChange handler to set some value on state as in the following:
<input type="text"
value={this.state.myValue}
onChange={val => this.setState({myValue: val},
()=> this validateMyValue(this.state.myValue))}} />
this.validateMyValue could be asynchronous, and do whatever is required if validation fails. That would be a controlled component doing what you want.
I'm trying to integrate react-day-picker's DayPicker with react-final-form.
React Final Form requires the use of a Field for each form field, which means creating an adapter component whenever you want to a third-party form element to be usable within the form. The adapter component has to accept an input object containing value and onChange. The advice is just to provide a new onChange.
This approach, which works for many other components, doesn't work for DayPicker. It seems like the issue is that DayPicker doesn't actually have an onChange method, so it's up to us to manage what happens when the calendar changes and then store the dates in value property that react-final-form expects.
I've created a codepen here: https://codesandbox.io/s/github/pcraig3/date-picker-sandbox
I have a handleDayClick method in Calendar.js which runs when days are clicked, but onChange isn't being triggered for the calendar consistently.
selectedDays is being updated immediately within the Calendar itself, but the Form is not getting the correct dates until the calendar is unfocused
The form's validate method is only being called once (the first time selecting a day), whereas it is called each time the native text input value is updated.
I would like the form values to be synced up with the calendar's external state and for the validate method to be triggered each time a day is clicked/unclicked. Is this possible to achieve or am I doing completely the wrong thing?
It's probably easier to use the <DayPickerInput> component, instead. That component uses a standard HTML input, which supports onChange. I did it like this:
<Field name={id}>
{({ input, meta }) => (
<React.Fragment>
<label htmlFor={id}>Date: </label>
<DayPickerInput
{...input}
onDayChange={day => input.onChange(day)}
inputProps={{ id: id }}
/>
{meta.error && meta.touched && <div className="error">{meta.error}</div>}
</React.Fragment>
)}
</Field>
According to the documentation, you can add the logic to the "inputProps" prop, since this takes in props to the input component, you can also add css to it as well.
inputProps Object
: Additional props to add to the input component.
Your code will look like this:
const dateChanged = day => (console.log(day)); //function to call when date changes
inputProps={{
style: styles.dayPickerInput,
onChange: event => dateChanged(event.target.value),
}}
If you use onDayChange alone, it'll fire after the user "clicks" to select a day, not when the user actually types a date inside the input field, using this extra onchange listener will be a safeguard for you, if the input field is enabled for users to type in the date, which they might.
I have a form, which is populated using various types of question fields (e.g. text input, email, number, radio box, tags, custom inputs ). These field types are fetched dynamically based on prior choices of user on a previous form.
Now, I have to validate the different form fields when user submits the form using React. The issue is that I can't simply check the value attribute of the fields, since some fields are complex and we get the value after applying some calculation, replacing-non-numbers, or some fields may have radio buttons and corresponding text inputs etc. How can I go about this validation in React? My general structure is this:
<form>
{ this.props.questions.map((question, index) => {
return <Question key={index} data={question} validationError={this.state.validationErrors[question.name]} />
})}
</form>
<button onClick={this.validateFields}>Submit</button>
Is it possible to loop through components in validateFields method of this component class? Or I need to loop through the html nodes that are rendered in the final HTML?
Earlier I was doing this using jQuery and was looping through the question div elements and applying custom validation rules depending on the question type (stored in a data attribute).
Now, I am not sure what is the correct way to do this in React.
You're applying jQuery (and vanilla JS) patterns of thinking to React. I suggest to stop considering you have DOM in any form. No DOM, no components list either, do not touch it or React will be a pain instead of help.
All the data you want to have must be in state. That's the purpose of this library.
So, in your case it is better to go this way:
1) Implement onChange event in Question and other field components. Regardless of how complex they are, your could stream their data into a signle argument, aren't you?
2) Add onChange handler in your form with something like
onChange={value =>
this.setState({
fieldValues: {
[index]: value
}
})
}
3) Populate fieldValues like this:
constructor(props) {
super(props);
this.state = {
fieldValues: props.questions,
};
}
And voila - all the form data are already in this.state.fieldValues, ready for any ongoing usage.
Surprised? So I was, when I first been understanding user input in React. Check this section in React docs for the source of the idea: https://reactjs.org/docs/forms.html#controlled-components
I have a form with some input fields (some of them hidden until a checkbox is checked. When I check/uncheck the checkbox a specific state is set (this.state.isChecked = true/false).
On render method, i have a div (containing some input fields) with some classes and this condition for "show" class: <div className={'extra-fields ' + (this.state.isChecked? ' show' : '')}>...</div>
Expected behavior is that on state change, only the "show" class is putted or deleted from div
Current behavior: the entire form is rendered again and all data written in the input fields are lost.
How it should be done this?
If the value of the input fields is important (which they apparently are), and if they can change (which the obviously can), then React should be aware of them, typically in state.
The 'standard' (on only) react way to maintain the contents of the input fields is:
put the content of the input fields in state as well,
include something like value={this.state.foo} and onChange={this._onChange()} to the render of each input field
include the _onChange() function to the form to handle input changes
That way, whenever the form is re-rendered (after each setState()), the input values are also preserved.
PS: The question title "stop reactjs component from rerender on state change" does not really cover the question from text: you are asking for a partial re-render: do re-render the show/hide extra fields based on checkbox, but do not re-render input fields.
The short answer is that you can prevent a component from rendering/updating with the shouldUpdateComponent life-cycle event: https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate
However, I agree with the previous answer, that for the sake of doing what sounds like a partial re-render, and to follow best practices in general, you should be storing the state of your input fields somewhere in a component so that they persist beyond a render call.