MUI error message alert showing although i dont want it to

Viewed 41

so I'm having some issues in my code which I'd like to get help with.

as you can see the error alert box is showing although it is supposed to be empty. I ran some code "tests" to see what is happening and rendered it on the page.

enter image description here

consts -

const [displayMessage, setDisplayMessage] = useState({});
const [errorMessage, setErrorMessage] = useState({
username: "",
email: "",
password: "",
});

useEffects -

 useEffect(() => {
    if (success) {
      setMessage(`${data.userName} has been created successfully`);
    }
  }, [data.userName, success]);

 useEffect(() => {
    if (typeof errorMessage === "string") {
      setDisplayMessage(errorMessage);
    } else {
      setDisplayMessage(
        Object.keys(errorMessage).map((key) => {
          return errorMessage[key];
        })
      );
    }
  }, [errorMessage]);

ternary operators -

        {typeof displayMessage} // "test"
        <br />
        {displayMessage.length} // "test"
        {Object.keys(displayMessage).map((key) => {
          console.log(displayMessage[key]);
        })}
        {displayMessage &&
          (typeof displayMessage === "string" ? (
            <Alert sx={{ mb: 4 }} severity="error">
              {displayMessage}
            </Alert>
          ) : (
            <Alert sx={{ mb: 4 }} severity="error">
              {Object.keys(displayMessage).map((key, index) => {
                return <div key={index}>{displayMessage[key]}</div>;
              })}
            </Alert>
          ))}

now as you can see here it's working the way I want it -

enter image description here

my only problem is that the alert box shows empty.

1 Answers

Objects such as {} don't have a length, so checking that's useless.

There's no point in trying to check the truthiness of the displayMessage object either, since empty objects are truthy:

> !!{}
true

If you want to figure out if an object is "empty" to hide the alert altogether, you could use e.g. Object.keys(displayMessage).length === 0.

All in all, I'd rewrite the alert-displaying bit to be a separate component that can deal with falsy values; then, deriving error messages from other state should be useMemo, not useEffect:

function MessagesAlert({message}) {
  if (!message) {  // No message.
    return null;
  }
  if (typeof message === 'string') {
    return <Alert sx={{mb: 4}} severity="error">
      {message}
    </Alert>;
  }
  const keys = Object.keys(message);
  if (!keys.length) { // No keys in message object.
    return null;
  }
  return (
    <Alert sx={{mb: 4}} severity="error">
      {keys.map((key, index) => {
        return <div key={index}>{message[key]}</div>;
      })}
    </Alert>
  );
}

function Component() {

  const errorMessages = React.useMemo(() => {
    const errors = {};
    if (something) errors.username = 'Username is required';
    return errors;
  }, [something]);

  return <MessagesAlert message={errorMessages} />;
}
Related