【问题标题】:React getting Maximum update depth exceeded error反应得到最大更新深度超出错误
【发布时间】:2019-10-09 17:01:35
【问题描述】:

我正在执行更改密码,对于 authError 我收到以下错误..

已超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。

更改密码.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);

修改密码操作

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

【问题讨论】:

  • 会不会是因为在每个&lt;TextField&gt; 中添加了onChange={this.handleChange}?现在,每次在文本字段中添加字符时,都会调用 handleChange 函数。
  • 我该如何处理?
  • 您可以在发布后立即处理所有数据,而不是单独处理每个文本字段。那么这不是您在changePassword 方法中已经在做的事情吗?为什么要在每个文本字段上使用单独的 handleChange 方法。据我所知,我认为handleChange 方法不会增加任何价值。
  • 没有句柄如何获取句柄提交中文本字段的值?
  • Upon further investigation,我建议您保持原样。这实际上是最好的方法。我不知道 React 处理 onChange 属性的方式与普通 HTML 不同。我个人从来没有像你一样需要输入值,因为我总是将表单数据发送到 API。我的错,对此感到抱歉。

标签: reactjs


【解决方案1】:

你正在这里更新状态

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

该行运行多次,因为它检查是否存在身份验证错误,是否有调用openSnackBaropenSnackBar 更新状态,这会导致组件重新渲染,重新渲染后检查再次发生等,这会导致循环。将其更改为以下内容,并且仅在 state.open 为 false 时调用 openSnackBar

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

编辑

从渲染中移除 authError 并签入componentDidMount

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

  if (authError) {
    this.openSnackbar({ message: '{authError}' });
  }
};

【讨论】:

  • 这消除了错误,但我认为它仍然会导致循环。我无法关闭小吃店。
  • 当你关闭循环时,它会将其设置为 false,然后再次进行检查。
  • 我在控制台中收到以下警告警告:在现有状态转换期间无法更新(例如在render 内)。渲染方法应该是 props 和 state 的纯函数。
  • 您是否从渲染中删除了{authError &amp;&amp; !this.state.open ? this.openSnackbar({ message: '{authError}' }) : null}
  • 这行得通,不会导致任何循环,但不会显示错误消息。
猜你喜欢
  • 2021-10-01
  • 1970-01-01
  • 2021-05-15
  • 2021-06-20
  • 1970-01-01
  • 2020-08-26
  • 2021-10-13
  • 2021-09-06
  • 1970-01-01
相关资源
最近更新 更多