Having trouble importing Material UI and working with ClickAwayListener

For my current project, I am utilizing material-ui to implement the functionality for changing passwords. In this root file, I am importing several child components:

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 '../component/Header';
import Sidebar from '../component/Sidebar';
import ChangeProfileImage from '../component/Main/PersonalizeMain/ChangeProfileImage';
import ChangePassword from '../component/Main/PersonalizeMain/ChangePassword';

const useStyles = makeStyles((theme) => ({
    root: {
        display: 'flex',
    },
    toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: theme.spacing(0, 1),
        marginTop: '65px',
        ...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);

One of the child components imported is ChangePassword, whose code is presented below.

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 encountered an issue when importing the ClickAwayListener to set the setError function to an empty string. Despite thorough checks, I could not pinpoint the cause of the following error message:

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

https://i.stack.imgur.com/DNEQT.png

Answer №1

ClickAwayListener can only have a single child component, not an array of components. Therefore, you need to modify your code as follows:

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

To this

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

This modification will make it function correctly once again.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unusual increase in the Date() function hour on March 12, 2017

I encountered an issue where creating a new Date() object for March 12, 2017 with the hour set to 2am displays as 3am when using getHours(). The expected output should be 2am. Could there be an error in my code? I have highlighted the problematic section ...

Node's getRandomValues() function is throwing an "expected Uint8Array" error

Currently, I am experimenting with the getRandomValues() function to enhance an encryption REST API that I am developing for practice. My server is using Node, which means I do not have access to a window object containing the crypto object normally housin ...

"Enhance Your Video Experience with a Personalized Play Button

Is it possible to customize the play icon for an embedded YouTube video? I came across a post discussing this topic: Can I change the play icon of embedded youtube videos? However, when trying to use something transparent as the new play button, the origin ...

What is the most efficient method for transferring Flask variables to Vue?

I am currently developing a visualization application using a flask server and vue.js for the front end. Other discussions on this topic explore how to avoid conflicts between vue.js and flask variable syntax, as shown here. In my scenario, I'm inte ...

Encountering Next.JS Router Issue: Unable to Access Properties of Null (specifically 'useContext')

As a beginner in Next.js and React, I'm facing an issue with redirecting users from the "Projects" page to the Product Page Details. Here's the code snippet I am using: const openProjectDetails = () => { Router.push('/api/' + props ...

A striking half-page visual showcasing the sleek design and functionality of MUI v

Trying to design a landing page using MUI v5 where one half features an image and the other half contains a login form. The goal is for both sections to fill the entire page without any scrolling required. Unfortunately, due to the MUI root's impact ...

The internal cjs loader in node threw an error at line 1078

I'm encountering an error on Windows 10 when running the npm command: node:internal/modules/cjs/loader:1063 throw err; ^ Error: Cannot find module 'D:\mobile-version portfolio\ at Module._resolveFilename (node:internal/modules/cjs/load ...

Dealing with lag problems while feeding a massive dataset into the Autocomplete component of Material-UI

In my React project, I have integrated the Autocomplete component from Material-UI to enhance user experience. However, when attempting to pass a large dataset of 10,000 items to the Autocomplete component as a prop, there is a noticeable delay of approxim ...

Updating the Navigation Bar after User Logs in

In the process of working on my assignment, I am in the midst of developing a web application. As someone who is new to using React, I'm currently trying to figure out how to modify my navbar once a user has logged in. For instance: Prior to logging ...

What is the best way to empty the input field after a download event is completed in Node.JS?

For hours on end, I've been struggling with a persistent issue in my video downloader app. After successfully downloading a video, the input field where the URL is entered remains filled instead of clearing out. The screenshot below illustrates the p ...

Update the value after verifying the element

I am trying to retrieve data from my database and update the values when an element is clicked (accepting user posts). The code I have written seems to work, but I encounter an error stating that props.actions is not a function when clicking on an element. ...

"Want to display a filter for a specific column in a Material UI React table? Here's

Is there a way to display the filter option only for specific columns, such as First Name, without it appearing on other columns like Id, Last Name, and Full Name? https://i.stack.imgur.com/HdBcp.png import React, { useEffect, useState } from "react& ...

When an array object is modified in Vue, it will automatically trigger the get method to validate any

One of the challenges I am facing is related to a button component that has a specific structure: <template> <button class="o-chip border-radius" :class="{ 'background-color-blue': theValue.isSelected, ...

What is the best way to anticipate a return phone call?

Looking to retrieve the largest date from a folder by reading its contents. https://i.stack.imgur.com/KYren.png Here is the code snippet to read the folder, extract filenames, and determine the largest date (excluding today): async function getLastDate ...

Implementing the linking of a URL to an HTML hidden button that is dynamically displayed through a Javascript program

I'm currently developing a basic webpage that has a feature allowing users to download the final result as an image file in the last step. To achieve this, I've added a hidden HTML button for downloading the result image and used CSS to set its ...

React client side componentDidMount function encountering issues (server side rendering)

Greetings to the Stackoverflow community Apologies in advance if my explanation is not clear enough When a user directly types a URL, the server makes a request, fetches the corresponding data, and renders it on the screen flawlessly. However, when a us ...

Is there a way to perform a nextAuth sign in using Postman?

I am currently working on implementing user authentication using NextAuth. The authentication works perfectly within my webapp, but now I want to test the sign-in functionality using Postman so that I can share the login endpoint. Below is the configuratio ...

Error encountered with default theme styling in Material-UI React TypeScript components

Currently, I am working on integrating Material-UI (v4.4.3) with a React (v16.9.2) TypeScript (v3.6.3) website. Following the example of the AppBar component from https://material-ui.com/components/app-bar/ and the TypeScript Guide https://material-ui.com/ ...

update-post-thumbnail wp-ajax return false

I have been attempting to utilize the media manager within Wordpress. I am using the post editor outside of the admin area, allowing users to create posts with a featured image. I have used the _wp_post_thumbnail_html function to display the image or provi ...

React Router Issue: Component Not Rendering When <nav> Element Is Incomplete

I am currently experiencing an issue with rendering a component in my React TypeScript application using React Router. The problem arises when trying to navigate to the AddTask component by clicking on a link within a <nav> element. Strangely, the co ...