onChange event issue with class component - javascript

I just want to get value from Radio component (checked or unchecked) in ui-semantic having following code:
componentDidMount() {
this.setState({
startDate: moment()
.subtract(30, 'days')
.startOf('day'),
endDate: moment().endOf('day'),
isChecked: false,
});
}
Radio component:
<Radio toggle className="ongoing-checkbox"
label="Show ongoing alerts"
value={ !this.state.isChecked }
onChange={e => this.selectOngoingAlerts(e)}></Radio>
and handler function:
selectOngoingAlerts = (e) => {
this.setState(this.state.isChecked = true);
const { householdAlerts } = this.props;
console.log('checked', this.state.isChecked);
}
How to have a state of Radio component in selectOngoingAlerts function? I want to make different actions with respect whether radio is checked or unchecked.

You need to accept the data / checked value from the second argument of the onChange callback. You were trying to assign the value in setState as well which is wrong. do it like you do in your componentDidMount
selectOngoingAlerts = (e, data) => {
this.setState({isChecked: data});
}
Also update the radio component to just pass the callback to your handler, you dont need or want a lambda here..
<Radio toggle className="ongoing-checkbox"
label="Show ongoing alerts"
value={ !this.state.isChecked }
onChange={this.selectOngoingAlerts} />
From the docs, the second argument is where the value is passed
You should be referencing the Checkbox docs like I linked because the Radio is syntactic sugar for <Checkbox radio />
Remember: setState is async, so you cannot console.log the value like you are trying to. Instead use a callback on setState if you really want to see its updated value, or just move your console.log to the render so you can see the value change on render cycles.

selectOngoingAlerts = (e) => {
const {isChecked} = this.state;
this.setState({ isChecked : !isChecked });
isChecked ? console.log('on') : console.log('off');
}

Related

how to prevent multiple function call in react js on value change

I want to prevent a multiple function call on user action .In my demo application I have a TABS and input field. I want to call a function on user TAB change and when user type anything on input field to call same function. Also reset the input field value when user change the tab .
Problem is my function is called twice when I change the tab. why ? I think it is due to setState only.
here is my code
https://codesandbox.io/s/sleepy-leaf-pi3ykn?file=/src/App.tsx
const AsyncCall = () => {
console.log("AsyncCallAsyncCallAsyncCallAsyncCall");
};
React.useEffect(() => {
console.log("init");
AsyncCall();
}, [value, textValue]);
React.useEffect(() => {
console.log("reset value");
setTextValue("");
}, [value]);
Step to reproduce
Run Application AsyncCall function call only one time
Type some text on input field example "abc". Every time it call function which is correct behaviour
clear console logs
Switch the second tab. if you see AsyncCall function call twice . I need to call only one time . NOT two times .this is the bug . I need to reset the input field also when user switch tabs
any way to prevent . I tried to use ref nothing works for me
I want to call function every textfield value change and tab change . But when user change Tab I need to reset the textfield value also
any suggestion ?
You can call your async call in TextField onChange like this
onChange={(e) => {
setTextValue(e.target.value);
AsyncCall();
}}
and can reset your value in Tabs onChange
handleChange = (event: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
setTextValue("");
}
Get rid of both useEffect they are unnecessary here
According to your need
I want to call function every textfield value change and tab change .
But when user change Tab I need to reset the textfield value also
Let see the issue in your code.
React.useEffect(() => {
console.log("init");
AsyncCall();
}, [value, textValue]);
When every value and textValue changes your useEffect gonna invoke. We can remove this useEffect if we call AsyncCall() method inside your valueChange method.
For text field
const handleTextChange = () => {
setTextValue(e.target.value);
AsyncCall();
}
<TextField
id="outlined-basic"
onChange={handleTextChange} // i name it handleTextChange
value={textValue}
label="Outlined"
variant="outlined"/>
Now whenever you textValue gonna change it will call AsyncCall() method.
For tabs
const handleChange = ()=>{
setValue(newValue);
// resetting text value as you want to reset it on tab change
setTextValue("");
// Calling AsyncCall() on Tab menu change
AsyncCall();
}
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
</Tabs>
Now, there is no need for these useEffects
React.useEffect(() => {
console.log("init");
AsyncCall();
}, [value, textValue]);
React.useEffect(() => {
console.log("reset value");
setTextValue("");
}, [value]);
Suggestion: For textValue you can use De-bounce technique to avid unnecessary re-rendering
https://www.freecodecamp.org/news/debouncing-explained/
Paste this code in your handleChange method
setValue(newValue);
setTextValue("")
and remove you second useEffect() hook
React.useEffect(() => {
console.log("reset value");
setTextValue("");
}, [value]);

React Hooks Onchange Synchronize

Im passing my app from the class model to the hooks and in my code y have a dropdown list that when executes the onChange method it does this:
filter(event)
{
this.setState({
selectedFilter: event.target.value
},() => { this.chargeInfo(); });
}
In my class model works perfectly, but i dont know how to do this with the hooks, im passing the method chargeInfo() and the variable selectedFilter by the props because this component is a child, so what I have is this code:
<Dropdown onChange={onChangeDropdown} />
const onChangeDropdown = function(event)
{
props.changeSelectedFilter(event.target.value);//this do setSelecedFilter in the parent
props.chargeInfo();//this is the method of the parent that do something
}
How can I adapt this in a Sync mode that execute first the props.changeSelectedFilter and later the props.chargeInfo?.
You may need to use the State Hook like this:
// setting up the default dropdown value
const [dropdownValue, setDropdownValue] = useState('Some Value');
// later, setting a new dropdown value
setDropdownValue('New Value')
See https://reactjs.org/docs/hooks-state.html for more info
I solved using useEffect:
useEffect(
() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
props.chargeInfo();}, [props.selectedFilter]
)
const onChangeDropdown = function(event)
{
props.changeSelectedFilter(event.target.value);
}
return(
<Dropdown style={{ marginRight: 10, }} value={props.selectedFilter} options={filters}
onChange={onChangeDropdown} optionLabel="name" placeholder="Filter by" />
)

I need to set the checkbox to enabled when its value is true

I need to set like if the value of check box is coming true then check box show selected if the value comes false check box gets selected but what happening its value getting true from the backend I am storing value in the state rules but it's not getting enable and if the value is getting true also I am not able to check and unchecked checkbox when value is true checkbox not check when value it's true why it's happening not sure also I am trying to set onChange but getting confused how to set onchange
value coming from backend
NameMatch: true
Match: true
SearchForm component
export default function SearchForm() {
const { setRules, rules, fetchSearch } = useRule();
const [changeRuleSettings, setChangeRuleSettings] = React.useState(false);
React.useEffect(() => {
fetchSearchRule();
}, []);
const handleCheckBoxChange = (e) => {
setRules((prevRules) => ({
...prevRules,
[e.target.name]: !prevState[e.target.checked],
}));
};
return (
<Grid item xs={4}>
<Box className={classes.formText}>
<Checkbox
style={style}
name="NameMatch"
checked={rules.NameMatch}
color="primary"
onChange={handleCheckBoxChange}
/>
<Typography variant="subtitle2" noWrap={true}>
Match
</Typography>
</Box>
</Grid>
)
}
If I am understanding the question correctly, you are asking what should the onChange function exactly do. So basically you need to switch the values of the property, that the Checkbox is dependent on. For example, if the backend returns :
exactNameMatch: true
partialNameMatch: true
Then for the first checkbox, when it is clicked, the value of exactNameMatch should be set to false. An example implementation would look something like this:
onChange={(e) => setRules((prevRules) => ({...prevRules, exactNameMatch: !prevRules.exactNameMatch}))}
For the second checkbox the onChange will be identical, with the small difference, that instead of exactNameMatch you would use partialNameMatch.
Another possibility is to implement the handleCheckBoxChange function like so:
const handleCheckBoxChange = (e) => {
setRules((prevRules) => ({...prevRules, [e.target.name]: !prevRules[e.target.name]}))
}
Where e.target.name is respectively exactNameMatch or partialNameMatch, based on the values you have passed to the name properties of the Checkbox component. Hope I managed to understand your problem correctly and actually help you!

Semantic-UI React Checkbox state not working

I've got a parent container that calls a class-based react component child (since the semantic-ui react docs are all written with class-based components). The child component has a Form.Field:
<Form.Field
control={Checkbox}
label={{children: 'cardreader'}}
checked = {this.state.cardReaderChecked}
onChange={this.cardReaderToggleHandler}
/>
I've got a state:
state = {
cardReaderChecked: false,
}
and a cardReaderToggleHandler:
cardReaderToggleHandler = () => {
console.log(this.state.cardReaderChecked);
this.setState((prevState, props) => ({
cardReaderChecked : !prevState.cardReaderChecked
}))
console.log(this.state.cardReaderChecked);
}
I've tried toggling on this.state.cardReaderChecked but I found a lot of references and docs recommending this approach with the prevState to avoid the delay in state updating.
However, there must a logical fault because it doesn't work. If I refresh the page, the checkbox is clear as this.state.cardReaderChecked.
The first time I click the checkbox it renders with the tick, and my this.state.cardReaderChecked updates to true (according to my trusty React tools in Chrome). However, both console.log printouts give me a false and if I pass my state back to the parent form, it also shows that the checkbox is false.
Every subsequent click toggles but a ticked checkbox shows a true state but passes on a false to the parent form (that's where the console.log is currently) and vice versa an unticked checkbox passes back a true.
I'm almost tempted to remove the not from the prev.state in the setState, but I would prefer to understand why this happens.
Bonus Question: How can I query the checkbox state checked in a functional component?
Pass the function to a child as prop
class Parent extends Component {
state = {
cardReaderChecked: false,
}
cardReaderToggleHandler = () => {
this.setState((prevState, props) => ({
cardReaderChecked : !prevState.cardReaderChecked
}), () => console.log(this.state.cardReaderChecked))
}
....
render () {
return (
....
<Form.Field
control={Checkbox}
label={{children: 'cardreader'}}
checked = {this.state.cardReaderChecked}
onChange={this.cardReaderToggleHandler}
/>
)
}

Can I set the state and call a function on one button click?

I have a button and when I click on it I'm using onClick to set the state and call a function. When I pair the two actions together, it seems to only set the state.
If I remove the sitting the state function, the handleClick function works. Can you have multiple function calls in an onClick function? I searched around here and found a post stating that you could, not sure if my code is incorrect.
class OverviewRender extends Component {
constructor(props) {
super(props);
this.state = {
Selected: 'MainMenu',
name: ''
}
}
componentDidUpdate() {
console.log("OverviewRENDER update name: " + this.state.name);
}
handleClick(e) {
e.preventDefault();
let helpFileName = this.state.name;
helpFileName = helpFileName.toLowerCase().trim();
//Cap the first letter in the name and add the rest of the name
helpFileName = helpFileName.charAt(0).toUpperCase() + helpFileName.substr(1);
this.props.handleHelpChange(helpFileName);
console.log("pressed " + helpFileName);
}
The button calling onClick...
<RaisedButton
label="Load Default Values"
name="One"
value={this.state.name}
onClick={() => {this.handleClick.bind(this), this.setState({ name: 'One' })}}
style={buttonStyle}
/>
That's because you're not executing the function. Function#bind returns a new function with the specified this and other supplied arguments bound. You have to execute it. Anyways, since you're using an arrow function, there's no need to bind anyway. Lastly, just set state inside handleClick, and pass in any variables you need to:
onClick={(e) => this.handleClick(e, 'One')}
And handleClick:
handleClick(e, num) {
this.setState({
name: num
}, () => {
e.preventDefault();
let helpFileName = this.state.name; //or num
helpFileName = helpFileName.toLowerCase().trim();
//Cap the first letter in the name and add the rest of the name
helpFileName = helpFileName.charAt(0).toUpperCase() + helpFileName.substr(1);
this.props.handleHelpChange(helpFileName);
console.log("pressed " + helpFileName);
});
}
Also note that I'm setting state first, then using a callback because setState is asynchronous. You have to wait until it is set to access it and get the right value.
You could either have the handleClick set the state, as mentioned in the previous answer, or your onClick could call handleClick in the callback:
<RaisedButton
label="Load Default Values"
name="One"
value={this.state.name}
onClick={() => { this.setState({ name: 'One' }, this.handleClick.bind(this) }}
style={buttonStyle}
/>

Categories

Resources