I am trying to figure out this issue where .toUpperCase() in one of my components is giving an error:
TypeError: Cannot read properties of undefined (reading 'toUpperCase')
I believe this is being caused because of a race condition in grabbing the prop in my reusable component called Icon as it happens about 50% of the time when I refresh the page.
import React from 'react';
import PropTypes from 'prop-types';
import './icons-svg-color.css';
const Icon = (props) => {
const { icon, className } = props;
return (
<div className={`icon-32 ${className}`} style={{ backgroundImage: `url('data:image/svg xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><style>.text {font-family: sans-serif; font-size: 10px; fill:#FFF;}</style><circle cx="16" cy="16" r="16" fill="#1d5baa"/><text x="50%" y="63%" text-anchor="middle" >${icon.toUpperCase()}</text></svg>')` }}>
<div className={`icon-32 ${className}`} style={{ backgroundImage: `url(/static/images/assets/icons/svg/color/${icon}.svg)` }} />
</div>
);
};
Icon.defaultProps = {
className: '',
};
Icon.propTypes = {
icon: PropTypes.string.isRequired,
className: PropTypes.string
};
export default Icon;
Here is where it is being used:
const renderMenuItems = () => {
return chartMarkets.map((type) => {
return (
<MenuItem value={type} onClick={event => handleSelection(event)}>
<Icon className={classes.menuItemImage} icon={type} />
<Typography variant="body1">{type}</Typography>
</MenuItem>
);
});
};
I have tried stuff like defaulting it to empty string, but that is not the outcome I want as the app no longer crashes but the icon is not there. I also have tried conditional rendering where I pass in the value into the prop after the value is defined like so:
<MenuItem value={type} onClick={event => handleSelection(event)}>
<Icon className={classes.menuItemImage} ***icon={type && type}*** />
<Typography variant="body1">{type}</Typography>
</MenuItem>
But still has the same issue where it crashes the program with that same error. Also have tried using useEffect in the reusable Icon component like so:
useEffect(() => {
}, [icon]);
Is there any other solutions that I can try? Thanks!
CodePudding user response:
You can do simple like
return (
icon && (<div className={`icon-32 ${className}`} style={{ backgroundImage: `url('data:image/svg xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"><style>.text {font-family: sans-serif; font-size: 10px; fill:#FFF;}</style><circle cx="16" cy="16" r="16" fill="#1d5baa"/><text x="50%" y="63%" text-anchor="middle" >${icon.toUpperCase()}</text></svg>')` }}>
<div className={`icon-32 ${className}`} style={{ backgroundImage: `url(/static/images/assets/icons/svg/color/${icon}.svg)` }} />
</div>)
);