ComponentDidMount не получает значение реквизита

Я выполняю опцию смены пароля с помощью react-redux-firestore. Смена пароля работает нормально, если все введено правильно. Если какая-либо ошибка аутентификации получена, ошибка отправляется, и это должно отображаться пользователю. Всякий раз, когда была получена ошибка аутентификации, я обрабатывал ее следующим образом, чтобы показать сообщение об ошибке в рендере.

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

но это делает бесконечный цикл.

Позже добавлен метод componentDidMount(). Это предотвратит зацикливание, но я не могу показать сообщение об ошибке.

    componentDidMount = () => {
        const { authError } = this.props;
        console.info(authError)
        if (authError) {
            this.setState(
                {
                    loading: false,
                    message: '{authError}',
                    open: true
                },
                () => {
                    alert(this.state.open);
                }
            )
        }

    };

когда я делаю console.info(authError).. сообщение об ошибке не отображается.

при нажатии кнопки, как я могу показать сообщение об ошибке?

Любая помощь приветствуется.

изменить компонент пароля

import React, { Component } from 'react'
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 {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            open: false,
            message: '',
            cp_currentPassword: '',
            cp_newPassword: '',
            cp_confirmPassword: ''
        }
    }
    componentDidMount = () => {
        const { authError } = this.props;
        console.info('did mount called')
        console.info(authError)
        if (authError) {
            this.setState(
                {
                    loading: false,
                    message: '{authError}',
                    open: true
                },
                () => {
                    alert(this.state.open);
                }
            )
        }

    };
    handleChangeEvent = (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.passwordUpdated)
    }
    passwordUpdated = () => {
        this.setState({
            message: 'Password changed Successfully.!',
            open: true,
            loading: false
        });
    };


    render() {
        const { classes, auth, authError } = this.props;

        console.info(authError)
        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>
                {/* {authError ? this.openSnackbar({ message: '{authError}' }) : null} */}

                <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.handleChangeEvent}
                                                        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.handleChangeEvent}
                                                        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.handleChangeEvent}
                                                        margin = "normal"
                                                        required = {true}
                                                    />
                                                </GridItem>
                                            </GridContainer>


                                        </CardBody>
                                        <CardFooter>

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

                    </GridItem>


                </GridContainer>


                <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, getState) => {
    return {
        changePassword: (currentPassword, newPassword, passwordUpdated) => { dispatch(changePassword(currentPassword, newPassword, passwordUpdated)) }
    }
}
export default compose(
    withStyles(styles),
    connect(mapstateToProps, mapDispatchtoProps)
)(ChangePassword);

действие авторизации

export const changePassword = (currentPassword, newPassword, func) => {
    return (dispatch, getState, { getFirebase }) => {
        const firebase = getFirebase();
        var user = firebase.auth().currentUser;
        var cred = firebase.auth.EmailAuthProvider.credential(
            user.email, currentPassword);
            // reauthenticateAndRetrieveDataWithCredential 
        user.reauthenticateWithCredential(cred)
            .then(() => {
                user.updatePassword(newPassword).then(() => {
                    console.info("Password updated!");
                    func();
                }).catch((error) => { dispatch({ type: 'CHANGEPASSWORD_ERR', error }) });
            }).catch((error) => {
                dispatch({ type: 'CHANGEPASSWORD_CURRPSW_ERR', error })
            });

    }
}

Редуктор авторизации

 case 'CHANGEPASSWORD_SUCCESS':
            return {
                ...state,
                 //action.func

            };  
            case 'CHANGEPASSWORD_CURRPSW_ERR':
            return {
                ...state,
                autherr: action.error.message

            };  
            case 'CHANGEPASSWORD_ERR':
                return {
                    ...state,
                    autherr: action.error.message

                };  

Пожалуйста, выложите весь код компонента

AdamGold 28.05.2019 08:06

выложил код компонента

ansh 28.05.2019 08:28
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
2
1 126
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, что то, чего вы пытаетесь достичь, связано не с реквизитом, а с состоянием (состояние Redux, которое передается props). Когда состояние изменяется, вы хотите, чтобы ошибка всплывала. В этом случае вы должны использовать componentDidUpdate, а не componentDidMount, потому что последний будет запускаться только один раз при монтировании компонента.

    componentDidUpdate = (prevProps) => {
        const { authError } = this.props;
        console.info(authError)
        if (authError != prevProps.authError) {
            this.setState(
                {
                    loading: false,
                    message: authError,
                    open: true
                },
                () => {
                    alert(this.state.open);
                }
            )
        }

    };

лучше сравнить точную опору, которая требует выполнения вышеуказанной логики, если есть другие опоры или состояние, которые будут меняться, это приведет к вечному циклу. поскольку вы вызываете setstate внутри.

Naresh Kumar 28.05.2019 08:19

Я согласен, хотя ansh не предоставил нам достаточно контекста, чтобы сделать это.

AdamGold 28.05.2019 08:20

Обновил мой код, не должен создавать бесконечный цикл.

AdamGold 28.05.2019 08:53

Просто установите открытый реквизит компонента Snackbar прямо из реквизита, например:

<Snackbar
    open = {!!this.props.authError}
    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 = {() =>{have a action dispatch for clear error added into the reducer}}
        >
            <CloseIcon className = {classes.icon} />
        </IconButton>
    }
    autoHideDuration = {3000}
/>

Другие вопросы по теме