O.Voronin
O.Voronin

Reputation: 3

why onclick called react material-ui

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

Answers (2)

3Dos
3Dos

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

Shubham Khatri
Shubham Khatri

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

Related Questions