Open jaydenseric opened 4 years ago
These situations may look edge case, but really they come up fairly often - maybe 5% of our project components.
Some examples:
import PropTypes from 'prop-types';
import { useEffect } from 'react';
import TagManager from 'react-gtm-module';
export default function GTMEventViewSearchResults({ categoryId }) {
useEffect(() => {
if (process.env.GTM_ID && categoryId)
TagManager.dataLayer({
dataLayer: {
event: 'view_search_results',
id: categoryId,
},
});
}, [categoryId]);
return null;
}
GTMEventViewSearchResults.propTypes = {
categoryId: PropTypes.string.isRequired,
};
import { MapContext } from '@urbica/react-map-gl';
import PropTypes from 'prop-types';
import { useContext } from 'react';
import useSupercluster from 'use-supercluster';
/**
* An alternative to the [`@urbica/react-map-gl-cluster`](https://github.com/urbica/react-map-gl-cluster)
* component [`Cluster`](https://urbica.github.io/react-map-gl-cluster/#/Cluster).
* @param {object} options Options.
* @param {Array<object>} options.points Supercluster points; an array of [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) objects. Each feature’s `geometry` must be a [GeoJSON Point](https://tools.ietf.org/html/rfc7946#section-3.1.2).
* @param {object} [options.options] Supercluster options.
* @param {Function} options.children React children render function.
* @returns {ReactNode} React children containing map markers.
* @see [GitHub issue for `Cluster` children not re-rendering on state updates](https://github.com/urbica/react-map-gl-cluster/issues/31).
*/
export default function MapCluster({ points, options, children }) {
const map = useContext(MapContext);
const { supercluster, clusters } = useSupercluster({
points,
bounds: map.getBounds().toArray().flat(),
zoom: map.getZoom(),
options,
});
return children(clusters, supercluster);
}
MapCluster.propTypes = {
points: PropTypes.arrayOf(
PropTypes.exact({
type: PropTypes.oneOf(['Feature']).isRequired,
geometry: PropTypes.exact({
type: PropTypes.oneOf(['Point']).isRequired,
coordinates: PropTypes.arrayOf(PropTypes.number.isRequired).isRequired,
}),
properties: PropTypes.object,
})
),
options: PropTypes.object,
children: PropTypes.func.isRequired,
};
I have one more example when propTypes are not removed:
import _RawContent from 'some-external-lib';
const RawContent = React.memo(props => (
<_RawContent {...props}>
{props.children}
</_RawContent>
));
RawContent.propTypes = {
children: _RawContent.propTypes.children,
};
export { RawContent };
But if I rewrite this functional component adding return
...
const RawContent = React.memo(props => {
return (
<_RawContent {...props}>
{props.children}
</_RawContent>
);
});
...
or doing something like that
...
const RawContentComponent = props => (
<_RawContent {...props}>
{props.children}
</_RawContent>
);
RawContentComponent.propTypes = {
children: _RawContent.propTypes.children,
};
export const RawContent = React.memo(RawContentComponent);
or even changing named export into default
...
const RawContent = props => (
<_RawContent {...props}>
{props.children}
</_RawContent>
);
RawContent.propTypes = {
children: _RawContent.propTypes.children,
};
export default React.memo(RawContent);
everything works fine.
We discovered this problem only because of this line children: _RawContent.propTypes.children,
as we got the error
raw-content.jsx:14 Uncaught TypeError: Cannot read property 'children' of undefined
.
For all of the following examples,
propTypes
are incorrectly not removed:Babel REPL
While this works: