admin管理员组

文章数量:1024603

I am using material-ui for my project and doing the password-changing functionality, this is my root file where I import children ponents:

Personalize.js

import React, { useContext, useState } from 'react';
import Cookies from 'universal-cookie';
import { makeStyles } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
import { Grid } from '@material-ui/core';
import { CurrentUserContext } from '../providers/CurrentUserContextProvider';

import Header from '../ponent/Header';
import Sidebar from '../ponent/Sidebar';
import ChangeProfileImage from '../ponent/Main/PersonalizeMain/ChangeProfileImage';
import ChangePassword from '../ponent/Main/PersonalizeMain/ChangePassword';

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
    },
    toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: theme.spacing(0, 1),
        marginTop: '65px',
        // necessary for content to be below app bar
        ...theme.mixins.toolbar,
    },
    content: {
        flexGrow: 1,
        padding: theme.spacing(3),
    },
}));

const Personalize = ({ history, location, match }) => {
    const classes = useStyles();
    const cookies = new Cookies();
    const token = cookies.get('token');

    if (token === undefined) {
        history.push('/login');
    }

    const { currentUser } = useContext(CurrentUserContext);
    const { profileImage } = currentUser;
    const [open, setOpen] = useState(false);

    const handleDrawerOpen = () => {
        setOpen(true);
    };

    const handleDrawerClose = () => {
        setOpen(false);
    };

    return (
        <div className={classes.root}>
            <Header open={open} handleDrawerOpen={handleDrawerOpen} />
            <Sidebar open={open} handleDrawerClose={handleDrawerClose} />
            <main className={classes.content}>
                <div className={classes.toolbar}>
                    <Grid container justify="space-evenly" alignItems="center">
                        <Grid item>
                            <ChangeProfileImage profileImage={profileImage} />
                        </Grid>

                        <Grid item>
                            <ChangePassword />
                        </Grid>
                    </Grid>
                </div>
            </main>
        </div>
    );
};

export default withRouter(Personalize);

As you can see I import a child ponent called ChangePassword, here is the code.

ChangePassword.js

import React, { useState } from 'react';
import Cookies from 'universal-cookie';
import { withRouter } from 'react-router-dom';
import { IconButton, TextField, Grid, Snackbar, ClickAwayListener } from '@material-ui/core';

import MuiAlert from '@material-ui/lab/Alert';

import VisibilityIcon from '@material-ui/icons/Visibility';
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';

import { makeStyles } from '@material-ui/core';

const Alert = (props) => {
    return <MuiAlert elevation={6} variant="filled" {...props} />;
};

const useStyles = makeStyles((theme) => ({
    MuiInputBaseInput: {
        '& .MuiInputBase-input': {
            minWidth: '300px',
        },
    },
    customePositionIconButton: { position: 'relative', top: '-50px', right: '-130px' },
}));

const ChangePassword = ({ history, location, match }) => {
    const classes = useStyles();
    const [passwordVisible, setPasswordVisible] = useState(false);
    const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false);
    const [error, setError] = useState('');
    const [open, setOpen] = useState(false);

    const [password, setPassword] = useState({
        newPass: '',
        confirmPass: '',
    });

    const cookies = new Cookies();
    const token = cookies.get('token');

    const handleSubmit = (event) => {
        var charCode = typeof event.which == 'number' ? event.which : event.keyCode;
        var { newPass, confirmPass } = password;
        if (charCode === 13) {
            if (confirmPass === '' || password === '') {
                return setError('Emptied Password');
            }

            if (newPass.trim() === confirmPass.trim()) {
                fetch('http://localhost:5000/users/me', {
                    method: 'PATCH',
                    headers: {
                        Authorization: 'Bearer '.concat(token),
                        'content-type': 'application/json; charset=UTF-8',
                    },
                    body: JSON.stringify({ newPass }),
                })
                    .then((response) => {
                        return response.json();
                    })
                    .then((json) => {
                        var { doc } = json;
                        if (doc) {
                            setOpen(true);
                        }
                    })
                    .catch((error) => {
                        console.error(error);
                    });
            } else {
                setError('Passwords Not Matched');
            }
        }
    };

    const handleClose = (event, reason) => {
        if (reason === 'clickaway') {
            return;
        }

        setOpen(false);
    };

    const handleClickAway = () => {
        setError('');
    };

    return (
        <ClickAwayListener onClickAway={handleClickAway}>
            <form noValidate autoComplete="off">
                <Grid container direction="column" justify="center" alignItems="center">
                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={passwordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="New Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, newPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>
                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setPasswordVisible(!passwordVisible);
                            }}
                        >
                            {passwordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>

                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={confirmPasswordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="Confirm Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, confirmPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>

                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setConfirmPasswordVisible(!confirmPasswordVisible);
                            }}
                        >
                            {confirmPasswordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>
                </Grid>
            </form>
            <Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
                <Alert onClose={handleClose} severity="success">
                    Password successfully changed
                </Alert>
            </Snackbar>
        </ClickAwayListener>
    );
};

export default withRouter(ChangePassword);

I have imported ClickAwayListener to setError to an emptied string, but I got this error and I can not understand why. I've already double checked and find no cause.

Element type is invalid: expected a string (for built-in ponents) or a class/function but got: undefined. You likely forgot to export your ponent from the file it's defined in, or you may have mixed up default and named imports

I am using material-ui for my project and doing the password-changing functionality, this is my root file where I import children ponents:

Personalize.js

import React, { useContext, useState } from 'react';
import Cookies from 'universal-cookie';
import { makeStyles } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
import { Grid } from '@material-ui/core';
import { CurrentUserContext } from '../providers/CurrentUserContextProvider';

import Header from '../ponent/Header';
import Sidebar from '../ponent/Sidebar';
import ChangeProfileImage from '../ponent/Main/PersonalizeMain/ChangeProfileImage';
import ChangePassword from '../ponent/Main/PersonalizeMain/ChangePassword';

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
    },
    toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: theme.spacing(0, 1),
        marginTop: '65px',
        // necessary for content to be below app bar
        ...theme.mixins.toolbar,
    },
    content: {
        flexGrow: 1,
        padding: theme.spacing(3),
    },
}));

const Personalize = ({ history, location, match }) => {
    const classes = useStyles();
    const cookies = new Cookies();
    const token = cookies.get('token');

    if (token === undefined) {
        history.push('/login');
    }

    const { currentUser } = useContext(CurrentUserContext);
    const { profileImage } = currentUser;
    const [open, setOpen] = useState(false);

    const handleDrawerOpen = () => {
        setOpen(true);
    };

    const handleDrawerClose = () => {
        setOpen(false);
    };

    return (
        <div className={classes.root}>
            <Header open={open} handleDrawerOpen={handleDrawerOpen} />
            <Sidebar open={open} handleDrawerClose={handleDrawerClose} />
            <main className={classes.content}>
                <div className={classes.toolbar}>
                    <Grid container justify="space-evenly" alignItems="center">
                        <Grid item>
                            <ChangeProfileImage profileImage={profileImage} />
                        </Grid>

                        <Grid item>
                            <ChangePassword />
                        </Grid>
                    </Grid>
                </div>
            </main>
        </div>
    );
};

export default withRouter(Personalize);

As you can see I import a child ponent called ChangePassword, here is the code.

ChangePassword.js

import React, { useState } from 'react';
import Cookies from 'universal-cookie';
import { withRouter } from 'react-router-dom';
import { IconButton, TextField, Grid, Snackbar, ClickAwayListener } from '@material-ui/core';

import MuiAlert from '@material-ui/lab/Alert';

import VisibilityIcon from '@material-ui/icons/Visibility';
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';

import { makeStyles } from '@material-ui/core';

const Alert = (props) => {
    return <MuiAlert elevation={6} variant="filled" {...props} />;
};

const useStyles = makeStyles((theme) => ({
    MuiInputBaseInput: {
        '& .MuiInputBase-input': {
            minWidth: '300px',
        },
    },
    customePositionIconButton: { position: 'relative', top: '-50px', right: '-130px' },
}));

const ChangePassword = ({ history, location, match }) => {
    const classes = useStyles();
    const [passwordVisible, setPasswordVisible] = useState(false);
    const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false);
    const [error, setError] = useState('');
    const [open, setOpen] = useState(false);

    const [password, setPassword] = useState({
        newPass: '',
        confirmPass: '',
    });

    const cookies = new Cookies();
    const token = cookies.get('token');

    const handleSubmit = (event) => {
        var charCode = typeof event.which == 'number' ? event.which : event.keyCode;
        var { newPass, confirmPass } = password;
        if (charCode === 13) {
            if (confirmPass === '' || password === '') {
                return setError('Emptied Password');
            }

            if (newPass.trim() === confirmPass.trim()) {
                fetch('http://localhost:5000/users/me', {
                    method: 'PATCH',
                    headers: {
                        Authorization: 'Bearer '.concat(token),
                        'content-type': 'application/json; charset=UTF-8',
                    },
                    body: JSON.stringify({ newPass }),
                })
                    .then((response) => {
                        return response.json();
                    })
                    .then((json) => {
                        var { doc } = json;
                        if (doc) {
                            setOpen(true);
                        }
                    })
                    .catch((error) => {
                        console.error(error);
                    });
            } else {
                setError('Passwords Not Matched');
            }
        }
    };

    const handleClose = (event, reason) => {
        if (reason === 'clickaway') {
            return;
        }

        setOpen(false);
    };

    const handleClickAway = () => {
        setError('');
    };

    return (
        <ClickAwayListener onClickAway={handleClickAway}>
            <form noValidate autoComplete="off">
                <Grid container direction="column" justify="center" alignItems="center">
                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={passwordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="New Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, newPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>
                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setPasswordVisible(!passwordVisible);
                            }}
                        >
                            {passwordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>

                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={confirmPasswordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="Confirm Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, confirmPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>

                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setConfirmPasswordVisible(!confirmPasswordVisible);
                            }}
                        >
                            {confirmPasswordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>
                </Grid>
            </form>
            <Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
                <Alert onClose={handleClose} severity="success">
                    Password successfully changed
                </Alert>
            </Snackbar>
        </ClickAwayListener>
    );
};

export default withRouter(ChangePassword);

I have imported ClickAwayListener to setError to an emptied string, but I got this error and I can not understand why. I've already double checked and find no cause.

Element type is invalid: expected a string (for built-in ponents) or a class/function but got: undefined. You likely forgot to export your ponent from the file it's defined in, or you may have mixed up default and named imports

Share Improve this question edited Oct 4, 2020 at 10:21 NearHuscarl 82.2k24 gold badges320 silver badges283 bronze badges asked Oct 4, 2020 at 6:55 Tam DoTam Do 3211 gold badge6 silver badges20 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

ClickAwayListener only accepts one child ponent, not array of ponents. So in your code, change this

<ClickAwayListener onClickAway={handleClickAway}>
  <form>
    {...}
  </form>
  <Snackbar />
</ClickAwayListener>

To this

<>
  <ClickAwayListener onClickAway={handleClickAway}>
    <form>
      {...}
    </form>
  </ClickAwayListener>
  <Snackbar />
</>

And it will work again.

I am using material-ui for my project and doing the password-changing functionality, this is my root file where I import children ponents:

Personalize.js

import React, { useContext, useState } from 'react';
import Cookies from 'universal-cookie';
import { makeStyles } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
import { Grid } from '@material-ui/core';
import { CurrentUserContext } from '../providers/CurrentUserContextProvider';

import Header from '../ponent/Header';
import Sidebar from '../ponent/Sidebar';
import ChangeProfileImage from '../ponent/Main/PersonalizeMain/ChangeProfileImage';
import ChangePassword from '../ponent/Main/PersonalizeMain/ChangePassword';

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
    },
    toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: theme.spacing(0, 1),
        marginTop: '65px',
        // necessary for content to be below app bar
        ...theme.mixins.toolbar,
    },
    content: {
        flexGrow: 1,
        padding: theme.spacing(3),
    },
}));

const Personalize = ({ history, location, match }) => {
    const classes = useStyles();
    const cookies = new Cookies();
    const token = cookies.get('token');

    if (token === undefined) {
        history.push('/login');
    }

    const { currentUser } = useContext(CurrentUserContext);
    const { profileImage } = currentUser;
    const [open, setOpen] = useState(false);

    const handleDrawerOpen = () => {
        setOpen(true);
    };

    const handleDrawerClose = () => {
        setOpen(false);
    };

    return (
        <div className={classes.root}>
            <Header open={open} handleDrawerOpen={handleDrawerOpen} />
            <Sidebar open={open} handleDrawerClose={handleDrawerClose} />
            <main className={classes.content}>
                <div className={classes.toolbar}>
                    <Grid container justify="space-evenly" alignItems="center">
                        <Grid item>
                            <ChangeProfileImage profileImage={profileImage} />
                        </Grid>

                        <Grid item>
                            <ChangePassword />
                        </Grid>
                    </Grid>
                </div>
            </main>
        </div>
    );
};

export default withRouter(Personalize);

As you can see I import a child ponent called ChangePassword, here is the code.

ChangePassword.js

import React, { useState } from 'react';
import Cookies from 'universal-cookie';
import { withRouter } from 'react-router-dom';
import { IconButton, TextField, Grid, Snackbar, ClickAwayListener } from '@material-ui/core';

import MuiAlert from '@material-ui/lab/Alert';

import VisibilityIcon from '@material-ui/icons/Visibility';
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';

import { makeStyles } from '@material-ui/core';

const Alert = (props) => {
    return <MuiAlert elevation={6} variant="filled" {...props} />;
};

const useStyles = makeStyles((theme) => ({
    MuiInputBaseInput: {
        '& .MuiInputBase-input': {
            minWidth: '300px',
        },
    },
    customePositionIconButton: { position: 'relative', top: '-50px', right: '-130px' },
}));

const ChangePassword = ({ history, location, match }) => {
    const classes = useStyles();
    const [passwordVisible, setPasswordVisible] = useState(false);
    const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false);
    const [error, setError] = useState('');
    const [open, setOpen] = useState(false);

    const [password, setPassword] = useState({
        newPass: '',
        confirmPass: '',
    });

    const cookies = new Cookies();
    const token = cookies.get('token');

    const handleSubmit = (event) => {
        var charCode = typeof event.which == 'number' ? event.which : event.keyCode;
        var { newPass, confirmPass } = password;
        if (charCode === 13) {
            if (confirmPass === '' || password === '') {
                return setError('Emptied Password');
            }

            if (newPass.trim() === confirmPass.trim()) {
                fetch('http://localhost:5000/users/me', {
                    method: 'PATCH',
                    headers: {
                        Authorization: 'Bearer '.concat(token),
                        'content-type': 'application/json; charset=UTF-8',
                    },
                    body: JSON.stringify({ newPass }),
                })
                    .then((response) => {
                        return response.json();
                    })
                    .then((json) => {
                        var { doc } = json;
                        if (doc) {
                            setOpen(true);
                        }
                    })
                    .catch((error) => {
                        console.error(error);
                    });
            } else {
                setError('Passwords Not Matched');
            }
        }
    };

    const handleClose = (event, reason) => {
        if (reason === 'clickaway') {
            return;
        }

        setOpen(false);
    };

    const handleClickAway = () => {
        setError('');
    };

    return (
        <ClickAwayListener onClickAway={handleClickAway}>
            <form noValidate autoComplete="off">
                <Grid container direction="column" justify="center" alignItems="center">
                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={passwordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="New Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, newPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>
                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setPasswordVisible(!passwordVisible);
                            }}
                        >
                            {passwordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>

                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={confirmPasswordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="Confirm Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, confirmPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>

                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setConfirmPasswordVisible(!confirmPasswordVisible);
                            }}
                        >
                            {confirmPasswordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>
                </Grid>
            </form>
            <Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
                <Alert onClose={handleClose} severity="success">
                    Password successfully changed
                </Alert>
            </Snackbar>
        </ClickAwayListener>
    );
};

export default withRouter(ChangePassword);

I have imported ClickAwayListener to setError to an emptied string, but I got this error and I can not understand why. I've already double checked and find no cause.

Element type is invalid: expected a string (for built-in ponents) or a class/function but got: undefined. You likely forgot to export your ponent from the file it's defined in, or you may have mixed up default and named imports

I am using material-ui for my project and doing the password-changing functionality, this is my root file where I import children ponents:

Personalize.js

import React, { useContext, useState } from 'react';
import Cookies from 'universal-cookie';
import { makeStyles } from '@material-ui/core/styles';
import { withRouter } from 'react-router-dom';
import { Grid } from '@material-ui/core';
import { CurrentUserContext } from '../providers/CurrentUserContextProvider';

import Header from '../ponent/Header';
import Sidebar from '../ponent/Sidebar';
import ChangeProfileImage from '../ponent/Main/PersonalizeMain/ChangeProfileImage';
import ChangePassword from '../ponent/Main/PersonalizeMain/ChangePassword';

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
    },
    toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: theme.spacing(0, 1),
        marginTop: '65px',
        // necessary for content to be below app bar
        ...theme.mixins.toolbar,
    },
    content: {
        flexGrow: 1,
        padding: theme.spacing(3),
    },
}));

const Personalize = ({ history, location, match }) => {
    const classes = useStyles();
    const cookies = new Cookies();
    const token = cookies.get('token');

    if (token === undefined) {
        history.push('/login');
    }

    const { currentUser } = useContext(CurrentUserContext);
    const { profileImage } = currentUser;
    const [open, setOpen] = useState(false);

    const handleDrawerOpen = () => {
        setOpen(true);
    };

    const handleDrawerClose = () => {
        setOpen(false);
    };

    return (
        <div className={classes.root}>
            <Header open={open} handleDrawerOpen={handleDrawerOpen} />
            <Sidebar open={open} handleDrawerClose={handleDrawerClose} />
            <main className={classes.content}>
                <div className={classes.toolbar}>
                    <Grid container justify="space-evenly" alignItems="center">
                        <Grid item>
                            <ChangeProfileImage profileImage={profileImage} />
                        </Grid>

                        <Grid item>
                            <ChangePassword />
                        </Grid>
                    </Grid>
                </div>
            </main>
        </div>
    );
};

export default withRouter(Personalize);

As you can see I import a child ponent called ChangePassword, here is the code.

ChangePassword.js

import React, { useState } from 'react';
import Cookies from 'universal-cookie';
import { withRouter } from 'react-router-dom';
import { IconButton, TextField, Grid, Snackbar, ClickAwayListener } from '@material-ui/core';

import MuiAlert from '@material-ui/lab/Alert';

import VisibilityIcon from '@material-ui/icons/Visibility';
import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';

import { makeStyles } from '@material-ui/core';

const Alert = (props) => {
    return <MuiAlert elevation={6} variant="filled" {...props} />;
};

const useStyles = makeStyles((theme) => ({
    MuiInputBaseInput: {
        '& .MuiInputBase-input': {
            minWidth: '300px',
        },
    },
    customePositionIconButton: { position: 'relative', top: '-50px', right: '-130px' },
}));

const ChangePassword = ({ history, location, match }) => {
    const classes = useStyles();
    const [passwordVisible, setPasswordVisible] = useState(false);
    const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false);
    const [error, setError] = useState('');
    const [open, setOpen] = useState(false);

    const [password, setPassword] = useState({
        newPass: '',
        confirmPass: '',
    });

    const cookies = new Cookies();
    const token = cookies.get('token');

    const handleSubmit = (event) => {
        var charCode = typeof event.which == 'number' ? event.which : event.keyCode;
        var { newPass, confirmPass } = password;
        if (charCode === 13) {
            if (confirmPass === '' || password === '') {
                return setError('Emptied Password');
            }

            if (newPass.trim() === confirmPass.trim()) {
                fetch('http://localhost:5000/users/me', {
                    method: 'PATCH',
                    headers: {
                        Authorization: 'Bearer '.concat(token),
                        'content-type': 'application/json; charset=UTF-8',
                    },
                    body: JSON.stringify({ newPass }),
                })
                    .then((response) => {
                        return response.json();
                    })
                    .then((json) => {
                        var { doc } = json;
                        if (doc) {
                            setOpen(true);
                        }
                    })
                    .catch((error) => {
                        console.error(error);
                    });
            } else {
                setError('Passwords Not Matched');
            }
        }
    };

    const handleClose = (event, reason) => {
        if (reason === 'clickaway') {
            return;
        }

        setOpen(false);
    };

    const handleClickAway = () => {
        setError('');
    };

    return (
        <ClickAwayListener onClickAway={handleClickAway}>
            <form noValidate autoComplete="off">
                <Grid container direction="column" justify="center" alignItems="center">
                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={passwordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="New Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, newPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>
                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setPasswordVisible(!passwordVisible);
                            }}
                        >
                            {passwordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>

                    <Grid item className={classes.MuiInputBaseInput}>
                        <TextField
                            type={confirmPasswordVisible ? 'text' : 'password'}
                            variant="outlined"
                            label="Confirm Password"
                            required
                            onChange={(event) => {
                                setError('');
                                setPassword({ ...password, confirmPass: event.target.value });
                            }}
                            onKeyDown={handleSubmit}
                            error={error === '' ? false : true}
                            helperText={error}
                        />
                    </Grid>

                    <Grid item>
                        <IconButton
                            className={classes.customePositionIconButton}
                            onClick={() => {
                                setConfirmPasswordVisible(!confirmPasswordVisible);
                            }}
                        >
                            {confirmPasswordVisible ? <VisibilityOffIcon /> : <VisibilityIcon />}
                        </IconButton>
                    </Grid>
                </Grid>
            </form>
            <Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
                <Alert onClose={handleClose} severity="success">
                    Password successfully changed
                </Alert>
            </Snackbar>
        </ClickAwayListener>
    );
};

export default withRouter(ChangePassword);

I have imported ClickAwayListener to setError to an emptied string, but I got this error and I can not understand why. I've already double checked and find no cause.

Element type is invalid: expected a string (for built-in ponents) or a class/function but got: undefined. You likely forgot to export your ponent from the file it's defined in, or you may have mixed up default and named imports

Share Improve this question edited Oct 4, 2020 at 10:21 NearHuscarl 82.2k24 gold badges320 silver badges283 bronze badges asked Oct 4, 2020 at 6:55 Tam DoTam Do 3211 gold badge6 silver badges20 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

ClickAwayListener only accepts one child ponent, not array of ponents. So in your code, change this

<ClickAwayListener onClickAway={handleClickAway}>
  <form>
    {...}
  </form>
  <Snackbar />
</ClickAwayListener>

To this

<>
  <ClickAwayListener onClickAway={handleClickAway}>
    <form>
      {...}
    </form>
  </ClickAwayListener>
  <Snackbar />
</>

And it will work again.

本文标签: javascriptMaterial UI unable to import and using ClickAwayListenerStack Overflow