I have a modal with some input fields. I can easily pass the data automatically with the user typing an input, using onChange function in the input field, as
<Input onChange={this.props.store.handleCategoryChange} type="text" />
and .. (Using a mobx store, irellevant though)
#observable categoryValue;
#action handleCategoryChange = (e, data) => {
this.categoryValue = data.value;
e.preventDefault();
};
However, I want to add a function where the user can pre-fill this with information elsewhere in the application. I have the data to pre-fill the input fields with, but I can't figure out how do actually input it programatically, without the user doing it?
I need to invoke the above handleCategoryChange function. But my variable would be equal to data.value .. Which presents a problem! Invoking this function by myself isn't possible, because I won't have the event e nor a value called data.value as I will "just" pass in a variable by itself.
What's the right way to programatically fill an input field automatically in React, using variables elsewhere? I need to invoke the onChange function somehow, but the input values will be different..
Use controlled component for this situation, define a value property of input element like this:
<Input value={variable_name} ....
Whenever you will update that variable, automatically that value will get populated in input element.
Now you can populate some default value by assigning a value to variable_name and user can update that value by onChange function.
As per DOC:
An input form element whose value is controlled by React in this way
is called a "controlled component".
Pass in the value property for input:
<input type="text" value={this.state.value} onChange={(e) => {this.setState({value: e.target.value })}/>
you can use the controlled component and pass the value to it.
<input type="text" value{this.state.value}
onChange={()=> {this.setState({value:e.target.value })}}
Good question. I'm having the same issue, and just found a solution.
The problem is that:
You can't just use the default state of the modal component to set the initial input value, because the modal renders one time within the parent component (starting off invisible), so the default state of the Modal wont keep up with any changes to the 'pre-filled' info in the store that the inputs within the modal require access to.
You can't use the value attribute of the input to reference some redux store prop, since this is needed to reference the onChange function so the user can make changes to that pre-filled info.
And, you can't use the onChange function to set the initial value, because it is required to update the local state with the users changes - not set an initial value. Anyway, this requires the user to click on something, and you want the modal inputs to be pre-populated before the user does anything as soon as the modal opens...
So. What we need is to update these input fields every time the Modal attribute isModalOpen (or whatever you are using) changes.
(ie, pre-populate the fields when the Modal is opened).
Again, note that opening the Modal is not RENDERING the modal, it was already rendered, once, and has sat there being invisible until that isModalOpen attribute changed to true.
The Solution:
Step 1: make a handler function in the Modal component that prefills the inputdata by updating the local state of the Modal component. Mine looks like this :
handlePreFillModalInputsOnOpen = () => {
this.setState(() => ({
orthForm: this.props.matchLexUnit['orthForm'],
orthVar: this.props.matchLexUnit['orthVar'],
oldOrthForm: this.props.matchLexUnit['oldOrthForm'],
oldOrthVar: this.props.matchLexUnit['oldOrthVar'],
source: this.props.matchLexUnit['source'],
namedEntityCheck: this.props.matchLexUnit['namedEntityCheck'],
styleMarkingCheck: this.props.matchLexUnit['styleMarkingCheck'],
artificialCheck: this.props.matchLexUnit['artificialCheck'],
error: ''
}));
};
Step 2: Make that function fire ONLY when the isOpen attribute of the modal changes from false to true.
(This is the meat of your problem I think).
Use the lifecycle method componentDidUpdate. This will execute every time the props of the modal change.
componentDidUpdate(prevProps) {
if (this.props.isModalOpen === true && prevProps.isModalOpen === false) {
this.handlePreFillModalInputsOnOpen();
}
}
Watch out
make sure that you have a conditional in componentDidUpdate, otherwise you can run into infinite-loop/performance issues
if you have the possibility of null values icoming in as the prefilled input info, make a null-check so that they will not be passed into the local state.
Hope this helps :)
How to Programmatically Prefill, Fill or Update input fields value in React or useState Hooks?
Firstly - Get and define the data from database
const **yourData** = isDataFromDatabase;
or if the data is stored in Redux, then...
const **yourData** = useSelector(isDataFromDatabase);
Secondly - append it as the default value of a useState hook
const [isDataValue, setIsDataValue] = useState(**yourData**);
Thirdly - create a function to watch and Update the changes made by the user to your data value and set it to the useState hook created above
/** handles Your Data Value */
const handleDataValue = (text) => {
setIsDataValue(text);
};
Lastly - in your input tag, use the useState State as the "Value" parameter so it can be updated with the onChange function
<input
className="css"
id="myDataInput"
type="text"
value={isDataValue}
placeholder={isDataValue}
onChange={(e) => handleDataValue(e.target.value)}
/>
Now when you load the component, the prefilled value will be shown and can be updated in the HTML Input field.
That's All.
Related
It's a basic question but I searched for a guide without success...
I want to have a list of dropdowns and inputs and each dropdown will change the input next to it.
var list = [{ name: "foo1"}, {name: "foo2"}];
return (
{list.map( (name) => {
return (<div>
<dropdown data={someData}
onChange={(ev) => {
if(ev.value == 'clearIt')
<CHANGE THE NEAR INPUT VALUE>
}
}/>
<input value={name.name} />
</div>)
})});
I don't want to use DOM nor ref cause I understood that it's better to avoid it.
Any suggestions?
Or maybe the ref is the only option?
Thanks
So you can achieve this by doing the following steps:
Create a new component and move the dropdown and input to this new component.
Add state to your component by following this example:
https://reactjs.org/docs/state-and-lifecycle.html#adding-local-state-to-a-class
Add an event listener onChange to the dropdown with an event handler which can update the state you created in the first step. (Remember to bind the handler in the constructor.
Add the new component within the div element of this example you gave and pass the relevant data you need to the new component you created.
This should allow you to update only the input next to the dropdown. Also it allows you to have different data for each dropdown you created.
I have an input type checkbox as follow:
const [is_checked,set_is_checked]= useState(false);
const toggle_payment = () => {
set_is_checked(!is_checked);
console.log(is_checked);
}
return(
<div>
<input checked={is_checked} onChange={toggle_value} type="checkbox"/>
</div>
)
The problem
This seems to work fine, But when I console.log(is_checked) it looks like it prints the previous value. I tried both onChange and onClick but got the same result. What confuses me is that the checkbox is getting checked / unchecked each time I click on the box, but the console.log prints different value than what expected to print, like when I check the box with the mouse click, the box got checked but the console.log prints false
the state update using the updater provided by useState hook is asynchronous, and will not immediately reflect and update but will trigger a re-render
i think that if you console.log() outside the function you might gonna see the changes of the is_checked
This is due to the way state management works in React. A call to a state setter function (in this case set_is_checked) will update the value, but that updated value is available on the next render. When you call console.log below set_is_checked, you are still referencing the old value prior to the state being set.
I have a form which loads with default values.
I want a button to reset all form's values to empty values.
The built in handleReset function only resets the values to the default values that the form was loaded with.
I tried to change the props with default values with concept similar to the code below, but the props are "read only".
resetToEmpty(){
this.props.user = {};
}
<button type="button" onClick={ resetToEmpty}>Clear form demo data</button>
Code sand box https://x7069jq8lz.codesandbox.io/
How could reset all formIk fields to empty values?
Thanks!
The code sand box is broken, but i think you should consider to change your props to empty in state above, and just add 'enableReinitializing' prop to your Formik instance.
Then after getting new props your initialValues in Formik should be updated.
You have to pass an empty user to your form component again. So you'll have to bubble up the reset event, that is, send it to form's parent component where you initially passed the user object.
Let's say that when you click the Reset button you'll have to do this where you're setting the user initially. As it's being passed as a prop to formik this should go in your parent component. Something like this:
user: { name: '', age: '', gender: null }
I am trying to update my state in ReactJS. To do this I have an input field in a Reactjs class. The field is automatically filled in with data from a parent class. The field looks like this:
<input
onChange={e => this.props.store.addLego(e)}
name="piece"
value={this.props.row.original.piece}
/>
The addLego function is designed to update my state and is in a MobX store. It looks like this:
addLego = action("addLego", e => {
this[e.target.name] = e.target.value;
});
However, I can't actually edit the input field! Nothing changes in the field when I type! Thanks for your help!
If you set a value attribute to an <input> field that field becomes a controlled input. This means that whatever gets passed to value is rendered on the screen. In your case, if you are not updating this.props.row.original.piece the <input> field will never get a new value. I'll suggest to read this bit of React's documentation https://reactjs.org/docs/forms.html#controlled-components
It is basically suggesting to keep the new value somewhere (in the component's state for example) and set it back as a value to the field.
Follow this tutorial here will solve your problem. It's a good read too for handling single or multiple inputs
Basically, you'll need a state in the constructor
this.state = {value: ''};
Event handler to set the value every onchange
handleChange(event) {
this.setState({value: event.target.value});
}
And the setup for input
<input type="text" value={this.state.value} onChange={this.handleChange} />
I actually have 2 combobox (react-widgets) on my reduxform.
My first combobox works perfectly because I fetch my datas onChange.
But when I focus the second one I want my data loaded in it depending on the value of the first one.
The problem is : I have data in the render when I console.log it but the component not rerendering. I have to type something in the field to see my data, it's like only the onchange trigger the rerendering.
Field in the form:
<Field
component={HouseComp}
name="house"
currenthouses={currenthousesValue}
onFocus={getHouses(props)}
{...props}
/>
My component render:
<Combobox id="house"
data={currenthouses}
{...input}
/>
the getHouses function is a fetch returning something like :
props.dispatch(change('form', 'currenthouses',data))
the currenthousesValue is from a selector:
const currenthousesValue = selector(state, 'currenthouses');
I tried to force the update by using componentDidUpdate but even if I see the call of my render function the UI is not refreshing.
I also tried to load the data on "onBlur" from the first one but same result.
I am new to React. But I faced a similar issue in React. In your case when the value of first combo box changes, The value of data attribute of second form also changes. But your second combobox is not re-rendering may be becuase it is not subscribed to componentWillReceiveProps event.
Something like this(taken from my code):
componentWillReceiveProps(nextProps) {
this.setState({
groups: nextProps.groups,
invoices_count: nextProps.groups.length
});
}