Reputation: 3
I write react component with dialog and list. When component recieve "open" prop and try to build list in render function, it's call onClick={ this.handleToggle(item.id) }
function of ListItem, so, that causes an infinite loop "render -> onClick -> setState -> render -> ... ". Why? And how can I get around this?
handleToggle(value) {
if (this.state.isLoading) {
return;
}
const {checked} = this.state;
const currentIndex = checked.indexOf(value);
const newSelected = checked.slice();
if (currentIndex === -1) {
newSelected.push(value);
} else {
newSelected.splice(currentIndex, 1);
}
this.setState({checked: newSelected});
}
render() {
if (!this.props.show) {
return null;
}
if (this.state.isLoading) {
return(<p>Loading...</p>);
}
const {classes, show, caption} = this.props;
const {checked, projects} = this.state;
return (
<Dialog
open={show}
onClose={this.onCancel}
aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">{caption}</DialogTitle>
<DialogContent>
<List>
{projects.map(item =>
<ListItem
key={item.id}
role={undefined}
dense
button
onClick={ this.handleToggle(item.id) }
className={classes.listItem}
>
<Checkbox
tabIndex={-1}
disableRipple
checked={checked.indexOf(item.id) !== -1}
/>
<ListItemText primary={item.name}/>
</ListItem>
) }
</List>
</DialogContent>
<DialogActions>
<Button onClick={this.onSuccess} color="primary">OK</Button>
<Button onClick={this.onCancel} color="secondary">Cancel</Button>
</DialogActions>
</Dialog>
);
}
Upvotes: 0
Views: 1272
Reputation: 3487
You have to write it like
onClick={ () => this.handleToggle(item.id) }
because writing onClick={ this.handleToggle(item.id) }
instantly calls the method instead of giving it as a callback to the onClick event
Upvotes: 4
Reputation: 281932
onClick={ this.handleToggle(item.id) }
will cause the handleToggle
function to be evaluated everytime render occurs and since you call a setState in handleToggle, it will go into an infinite loop. onClick expects a function and you should write it like
onClick={() => this.handleToggle(item.id) }
this will cause handleToggle to be called only on a click
event
Upvotes: 1