expo / vector-icons

https://icons.expo.fyi
MIT License
647 stars 114 forks source link

SDK51 : Property 'Icon' doesn't exist #303

Open lc3t35 opened 1 month ago

lc3t35 commented 1 month ago

image

The source code of build/createIconSet.js :

export default function (glyphMap, fontName, expoAssetId, fontStyle) {
    const font = { [fontName]: expoAssetId };
    const RNVIconComponent = createIconSet(glyphMap, fontName, null, fontStyle);
    return class Icon extends React.Component {
        static defaultProps = RNVIconComponent.defaultProps;
        static Button = createIconButtonComponent(Icon);                    ====> Icon does not exist in the js file !
geovane7881 commented 1 month ago

same problem here, version 14 broke my icons, I workaround using version 13:

"@expo/vector-icons": "^13.0.0"

lc3t35 commented 1 month ago

In version 13, the code seems to be based on a React.Component not a function -> workaround is also working for me. Thank you @geovane7881

brentvatne commented 4 weeks ago

hi there! do you have a minimal reproducible example that you can share?

lc3t35 commented 2 weeks ago

@brentvatne I gave the exact location of the issue (build/createIconSet.js), the previous code @13.0.0 works and the new code @14.0.0 does not work.

The code in @14 returns a class Icon extends React.Component and uses Icon inside the function which is not correct, the code in 13 (as a component) stores the class in a var _a :

    var _a;
    const font = { [fontName]: expoAssetId };
    const RNVIconComponent = createIconSet(glyphMap, fontName, null, fontStyle);
    return _a = class Icon extends React.Component {
            constructor() { ...},
           ...
        }, 
        _a.defaultProps = RNVIconComponent.defaultProps,
        _a.Button = createIconButtonComponent(_a),
       ....
       _a;
   }

This looks like a generated code ... from ts or babel ? It's interesting to know why the @14 code was not generated this way ... Easy to fix, store the class, update the props Button and others, return the modified class ...

Do you really need a reproducible example ?

lc3t35 commented 2 days ago

This is how I fixed this error :

export default function (glyphMap, fontName, expoAssetId, fontStyle) {
    const font = { [fontName]: expoAssetId };
    const RNVIconComponent = createIconSet(glyphMap, fontName, null, fontStyle);
    class Icon extends React.Component {
        static defaultProps = RNVIconComponent.defaultProps;
        static glyphMap = glyphMap;
        static getRawGlyphMap = () => glyphMap;
        static getFontFamily = () => fontName;
        static loadFont = () => Font.loadAsync(font);
        static font = font;
        _mounted = false;
        _icon;
        state = {
          fontIsLoaded: Font.isLoaded(fontName),
        };
        async componentDidMount() {
          this._mounted = true;
          if (!this.state.fontIsLoaded) {
            await Font.loadAsync(font);
            /* eslint-disable react/no-did-mount-set-state */
            this._mounted && this.setState({ fontIsLoaded: true });
          }
        }
        componentWillUnmount() {
          this._mounted = false;
        }
        setNativeProps(props) {
          if (this._icon) {
            this._icon.setNativeProps(props);
          }
        }
        render() {
          if (__DEV__ && this.props.name && !(this.props.name in glyphMap)) {
            console.warn(`"${this.props.name}" is not a valid icon name for family "${fontName}"`);
          }
          if (!this.state.fontIsLoaded) {
            return <Text />;
          }
          return (<RNVIconComponent ref={(view) => {
            this._icon = view;
          }} {...this.props}/>);
        }
      };

      Icon.Button = createIconButtonComponent(Icon); // Move this line after the class definition

      return Icon;
}
lc3t35 commented 1 day ago

And the patch file @expo+vector-icons+14.0.2.patch for anybody who has the issue and wants to use 14.0.2 :

diff --git a/node_modules/@expo/vector-icons/build/createIconSet.js b/node_modules/@expo/vector-icons/build/createIconSet.js
index e8e1ec0..41d085a 100644
--- a/node_modules/@expo/vector-icons/build/createIconSet.js
+++ b/node_modules/@expo/vector-icons/build/createIconSet.js
@@ -7,9 +7,9 @@ export { DEFAULT_ICON_COLOR, DEFAULT_ICON_SIZE, } from './vendor/react-native-ve
 export default function (glyphMap, fontName, expoAssetId, fontStyle) {
     const font = { [fontName]: expoAssetId };
     const RNVIconComponent = createIconSet(glyphMap, fontName, null, fontStyle);
-    return class Icon extends React.Component {
+    
+    class Icon extends React.Component {
         static defaultProps = RNVIconComponent.defaultProps;
-        static Button = createIconButtonComponent(Icon);
         static glyphMap = glyphMap;
         static getRawGlyphMap = () => glyphMap;
         static getFontFamily = () => fontName;
@@ -18,35 +18,39 @@ export default function (glyphMap, fontName, expoAssetId, fontStyle) {
         _mounted = false;
         _icon;
         state = {
-            fontIsLoaded: Font.isLoaded(fontName),
+          fontIsLoaded: Font.isLoaded(fontName),
         };
         async componentDidMount() {
-            this._mounted = true;
-            if (!this.state.fontIsLoaded) {
-                await Font.loadAsync(font);
-                /* eslint-disable react/no-did-mount-set-state */
-                this._mounted && this.setState({ fontIsLoaded: true });
-            }
+          this._mounted = true;
+          if (!this.state.fontIsLoaded) {
+            await Font.loadAsync(font);
+            /* eslint-disable react/no-did-mount-set-state */
+            this._mounted && this.setState({ fontIsLoaded: true });
+          }
         }
         componentWillUnmount() {
-            this._mounted = false;
+          this._mounted = false;
         }
         setNativeProps(props) {
-            if (this._icon) {
-                this._icon.setNativeProps(props);
-            }
+          if (this._icon) {
+            this._icon.setNativeProps(props);
+          }
         }
         render() {
-            if (__DEV__ && this.props.name && !(this.props.name in glyphMap)) {
-                console.warn(`"${this.props.name}" is not a valid icon name for family "${fontName}"`);
-            }
-            if (!this.state.fontIsLoaded) {
-                return <Text />;
-            }
-            return (<RNVIconComponent ref={(view) => {
-                    this._icon = view;
-                }} {...this.props}/>);
+          if (__DEV__ && this.props.name && !(this.props.name in glyphMap)) {
+            console.warn(`"${this.props.name}" is not a valid icon name for family "${fontName}"`);
+          }
+          if (!this.state.fontIsLoaded) {
+            return <Text />;
+          }
+          return (<RNVIconComponent ref={(view) => {
+            this._icon = view;
+          }} {...this.props}/>);
         }
-    };
+      };
+    
+      Icon.Button = createIconButtonComponent(Icon); // Move this line after the class definition
+    
+      return Icon;
 }
 //# sourceMappingURL=createIconSet.js.map
\ No newline at end of file

I tryed to provide a reproduction repo but it does happen with the simple repo I've built ...