0

I'm performing a change password, for authError I'm getting the following error..

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

changepassword.js

import React, { Component } from 'react'
import withStyles from "@material-ui/core/styles/withStyles";
import { Redirect } from 'react-router-dom'
import IconButton from '@material-ui/core/IconButton';
import { connect } from 'react-redux'
import { compose } from 'redux'
import {changePassword } from '../../store/actions/auth'

const styles = {
     textField: {
      fontSize: '5px'
    },

  };

class ChangePassword extends Component {
    state = {
        loading: false,
        open:false,
        message:'',
        cp_currentPassword: '',
        cp_newPassword: '',
        cp_confirmPassword: ''
    }
    handleChange = (e) => {
        this.setState({
            [e.target.id]: e.target.value
        })
    }
    openSnackbar = ({ message }) => {
        this.setState({
            open: true,
          message,
        });
      };
      handleSubmit = (e) => {
        e.preventDefault();
        let curpass=this.state.cp_currentPassword
        let newpass=this.state.cp_newPassword
        this.setState({loading:true});
        this.props.changePassword(curpass,newpass)
        this.openSnackbar({ message: 'Password changed Successfully.!' })
        }

    render() {
        const { classes, auth, authError } = this.props;
        const { loading } = this.state;
        const message = (
            <span
              id="snackbar-message-id"
              dangerouslySetInnerHTML={{ __html: this.state.message }}
            />
          );
          if (!auth.uid) return <Redirect to='/signin' />
        return (
            <div>
                <GridContainer>
                    <GridItem xs={12} sm={12} md={12}>

                        <Card>
                            <CardHeader color="warning">
                                <h4 className={classes.cardTitleWhite}>Change Password</h4>
                            </CardHeader>
                            <form >
                            <GridContainer>
                            <GridItem xs={12} sm={12} md={6}>
                                <CardBody>
                                    <GridContainer>
                                        <GridItem xs={12} sm={12} md={12}>

                                            <TextField
                                                id="cp_currentPassword"
                                                label="Current Password"
                                                type="password"
                                                fullWidth
                                                className={classes.textField}
                                                value={this.state.cp_currentPassword}
                                                onChange={this.handleChange}
                                                margin="normal"
                                                required={true}
                                            />
                                        </GridItem>

                                        <GridItem xs={12} sm={12} md={12}>
                                            <TextField
                                                id="cp_newPassword"
                                                label="New Password"
                                                type="password"
                                                fullWidth
                                                className={classes.textField}
                                                value={this.state.cp_newPassword}
                                                onChange={this.handleChange}
                                                margin="normal"
                                                required={true}
                                            />
                                        </GridItem>
                                        <GridItem xs={12} sm={12} md={12}>
                                            <TextField
                                                id="cp_confirmPassword"
                                                label="Confirm Password"
                                                type="password"
                                                fullWidth
                                                className={classes.textField}
                                                value={this.state.cp_confirmPassword}
                                                onChange={this.handleChange}
                                                margin="normal"
                                                required={true}
                                            />
                                        </GridItem>
                                    </GridContainer>


                                </CardBody>
                                <CardFooter>

                                    <Button color="warning" onClick={this.handleSubmit} disabled={loading}>
                                        {loading && <CircularProgress style={{ color: 'white', height: '20px', width: '20px', marginRight: '10px' }} />}
                                        Change Password
                      </Button>
                                </CardFooter>
                                </GridItem>
                                </GridContainer>
                            </form>
                        </Card>

                    </GridItem>


                </GridContainer>
                {authError ? this.openSnackbar({ message: '{authError}' }) : null}

<Snackbar
    open={this.state.open}
    anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
    message={message}
    variant="error"
    onClose={() => this.setState({ open: false, message: '' })}
    action={
        <IconButton
            key="close"
            aria-label="Close"
            color="inherit"
            className={classes.close}
            onClick={() => this.setState({ open: false, message: '' })}
        >
            <CloseIcon className={classes.icon} />
        </IconButton>
    }
    autoHideDuration={3000}
/>
            </div>
        )
    }
}
const mapstateToProps = (state) => {
    return {
      auth: state.firebase.auth,
      authError: state.authroot.autherr
    }
  }
  const mapDispatchtoProps = (dispatch) => {
    return {
        changePassword: (currentPassword,newPassword) => { dispatch(changePassword(currentPassword,newPassword)) }
    }
  }
export default compose(
    withStyles(styles),
    connect(mapstateToProps,mapDispatchtoProps)
  )(ChangePassword);

change password action

export const changePassword = (currentPassword, newPassword) => {
    return (dispatch, getState, { getFirebase }) => {
        const firebase = getFirebase();
        console.log(currentPassword);
        console.log(newPassword);
        var user = firebase.auth().currentUser;
        user.updatePassword(newPassword).then(() => {
            console.log("Password updated!");
        }).catch((error) => { 
            dispatch({ type: 'CHANGEPASSWORD_ERR', error })});
}
}
5
  • Could it be that the cause is with adding onChange={this.handleChange} to every <TextField>? Right now for every time you add a character in the textfield you call the handleChange function. Commented May 23, 2019 at 7:17
  • How can I handle this ? Commented May 23, 2019 at 11:34
  • You could process all the data at once after posting instead of individually handeling each text field. Then again isn't that what you are already doing inside the changePassword method? Why would you use a separate handleChange method on each text field. As far as I can tell I don't think that the handleChange method adds any value. Commented May 23, 2019 at 12:11
  • without handle how can i get the value of textfield in handlesubmit? Commented May 23, 2019 at 12:39
  • Upon further investigation, I do recommend keeping it the way you have it. That is actually the best way. I didn't know that React handles the onChange propery differently than regular HTML does. I personally have never needed input values the same way you do since I've always send my form data to an API. My bad, sorry about that. Commented May 23, 2019 at 12:54

1 Answer 1

1

You are updating state here

{authError ? this.openSnackbar({ message: '{authError}' }) : null

that line runs multiple times, as it checks if there was auth error, if there was call openSnackBar, openSnackBar update state, which cause the component to re-render, after re-render the check happens again etc, which causes a loop. change it to the following and only call openSnackBar when state.open is false.

{authError && !this.state.open ? this.openSnackbar({ message: '{authError}' }) : null}

EDIT

remove authError from render and check in componentDidMount

componentDidMount = () => {
  const { authError } = this.props;

  if (authError) {
    this.openSnackbar({ message: '{authError}' });
  }
};
Sign up to request clarification or add additional context in comments.

6 Comments

this removes the error, but i think still it is causing a loop. i cannot close the snackbar.
when you close the loop, it sets it to false, and the check happens again.
im getting the following warning in console Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
did you remove {authError && !this.state.open ? this.openSnackbar({ message: '{authError}' }) : null} from render?
this works, not causing any loop, but its not showung error message.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.