How to toggle checkbox value in React Hooks? - javascript

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.

Related

React onLoad callback should set state of element, but does not do so, because onLoad is not called

I have a load of custom checkboxes that look like this:
<CustomCheckbox className='' name='foo' text='Foo' defaultState={false} onChange={this.handleChange} onLoad={this.handleChange}/>
Which are components of this form:
export const CustomCheckbox = (props) => {
return (
<label htmlFor={props.name} className={`customCheckboxLabel ${props.className}`}>
<input type='checkbox' name={props.name} id={props.name} className='customCheckboxInput' onChange={props.onChange} onLoad={props.onLoad} defaultChecked={props.defaultState}/>
<span>{props.text}</span>
</label>
)
}
onChange:
handleChange = e => this.setState({ [e.target.name]: e.target.checked })
In terms of onChange, this works fine, however, onLoad is not being called. I actually want onChange and onLoad to be the same function, as that way, the checkboxes will automatically populate the state with their (initially unchecked) values, and update them to checked if the user checks them.
The reason I want to do this, is that I later need to submit the whole checkbox array (both checked and unchecked). The number and values of checkboxes are likely to be changed regularly, so I don't want to have to define foo: false for every checkbox in the constructor of the page, as this seems to violate DRY (and would be a pain, since adding a checkbox would mean adding the component, and adding it to the initial state)
Desired behaviour:
handleChange called when each checkbox initially loads, so that the state contains name: initialstate for every checkbox, handleChange called again on change, to record if checkbox state is changed from initialstate.
Current behaviour:
onLoad function is never called.

Updating state in Reactjs?

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

React widget Combobox not updating onFocus with Reduxform

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

How do I programatically fill input field value with React?

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.

Getting value from mdl radio button

In the following code why doesn't the radio report the correct value when checked via its variable name?
var $myRadio = $('input[type=radio][name=options]:checked');
$('#button').click(() => {
// this works
console.log($('input[type=radio][name=options]:checked').val());
// this doesn't :(
console.log($myRadio.val());
});
https://jsfiddle.net/charsi/p4beztwx/13/
I am using mdl radio buttons so that could be causing it. I have also tried getting the value with $myRadio[0].MaterialRadio.value but that doesn't work either.
EDIT: This was a poorly worded question and didn't really have anythng to do with mdl. What I really wanted was the ability to set the DOM variable for my radio button somewhere else without having to select it by name again to check the value.
The reason for getting incorrect values when checked via its variable name is because you are setting $myRadio before the click event. $myRadio is set on document ready (before click event) and it gets the value of the checked radio option which at this moment is always 1.
Moving $myRadio inside a click handler should work. Why? Because now it gets the value of the radio (checked) as soon as the click function is called which is actually what you need.
$('#button').click(() => {
var $myRadio = $('[id^="option"]:checked');
// neither of these work
alert($('input[type=radio][name=options]:checked').val());
alert($myRadio.val());
});
fiddle here
For anyone else running into the same issue. Not wanting to call the radio button name when checking for its value, you can use filter -
var $myRadio = $('input[type=radio][name=options]');
$('#button').click(() => {
console.log($myRadio.filter(':checked').val());
}

Categories

Resources