react-native-scalable-image icon indicating copy to clipboard operation
react-native-scalable-image copied to clipboard

React 0.74 - Update defaultProps to JavaScript default parameters.

Open bruce-mec opened this issue 1 year ago • 3 comments

After updating to React Native 0.74, the following error/warning is produced.

Support for defaultProps will be removed from function components in a future major release. 
Use JavaScript default parameters instead.

RN 0.74 RNSI 1.1.0

bruce-mec avatar May 16 '24 13:05 bruce-mec

I have updated the ScalableImage component to use JavaScript default parameters instead of defaultProps. Below is the patch you can use to fix this issue:

Patch File

Create a file named react-native-scalable-image+1.1.0.patch in the patches directory of your project with the following content:

diff --git a/node_modules/react-native-scalable-image/index.js b/node_modules/react-native-scalable-image/index.js
index 655e3b3..44b65ff 100644
--- a/node_modules/react-native-scalable-image/index.js
+++ b/node_modules/react-native-scalable-image/index.js
@@ -1,123 +1,125 @@
-import React, {
-    useState,
-    useEffect,
-    useRef
-} from 'react';
+import React, {useState, useEffect, useRef} from "react";
 
-import PropTypes from 'prop-types';
+import PropTypes from "prop-types";
 
-import {
-    Image,
-    TouchableOpacity,
-    ImageBackground
-} from 'react-native';
+import {Image, TouchableOpacity, ImageBackground} from "react-native";
 
 const resolveAssetSource = Image.resolveAssetSource;
 
-const ScalableImage = props => {
-    const ImageComponent = props.component
-        ? props.component
-        : props.background
-            ? ImageBackground
-            : Image;
-
-    const [scalableWidth, setScalableWidth] = useState(null);
-    const [scalableHeight, setScalableHeight] = useState(null);
-    const [image, setImage] = useState(null);
-    const mounted = useRef(false);
-
-    useEffect(() => {
-        mounted.current = true;
-
-        return () => {
-            mounted.current = false;
-        }
-    }, []);
-
-    useEffect(() => {
-        onProps(props);
-    });
-
-    useEffect(() => {
-        setImage(
-            <ImageComponent
-                {...props}
-                style={[props.style, {
-                    width: scalableWidth,
-                    height: scalableHeight
-                }]}
-            />
-        );
-    }, [scalableHeight, scalableWidth]);
-
-    const onProps = localProps => {
-        const { source } = localProps;
-        if (source.uri) {
-            const sourceToUse = source.uri
-                ? source.uri
-                : source;
-
-            Image.getSize(
-                sourceToUse,
-                (width, height) => adjustSize(width, height, props),
-                console.err
-            );
-        }
-        else {
-            const sourceToUse = resolveAssetSource(source);
-            adjustSize(sourceToUse.width, sourceToUse.height, props);
-        }
-    };
-
-    const adjustSize = (sourceWidth, sourceHeight, localProps) => {
-        const { width, height } = localProps;
-
-        let ratio = 1;
-
-        if (width && height) {
-            ratio = Math.min(width / sourceWidth, height / sourceHeight);
-        }
-        else if (width) {
-            ratio = width / sourceWidth;
-        }
-        else if (height) {
-            ratio = height / sourceHeight;
-        }
-
-        if (mounted.current) {
-            const computedWidth = sourceWidth * ratio;
-            const computedHeight = sourceHeight * ratio;
-
-            setScalableWidth(computedWidth);
-            setScalableHeight(computedHeight);
-
-            props.onSize({ width: computedWidth, height: computedHeight });
-        }
-    };
-
-    if (!props.onPress) {
-        return image;
-    }
-    else {
-        return (
-            <TouchableOpacity onPress={props.onPress}>
-                {image}
-            </TouchableOpacity>
-        );
-    }
+const ScalableImage = ({
+	component,
+	background = false,
+	onSize = (size) => {},
+	width,
+	height,
+	onPress,
+	style,
+	source,
+	...props
+}) => {
+	const newCompinedProps = {
+		component,
+		background,
+		onSize,
+		width,
+		height,
+		onPress,
+		style,
+		source,
+		...props,
+	};
+
+	const ImageComponent = component
+		? component
+		: background
+		? ImageBackground
+		: Image;
+
+	const [scalableWidth, setScalableWidth] = useState(null);
+	const [scalableHeight, setScalableHeight] = useState(null);
+	const [image, setImage] = useState(null);
+	const mounted = useRef(false);
+
+	useEffect(() => {
+		mounted.current = true;
+
+		return () => {
+			mounted.current = false;
+		};
+	}, []);
+
+	useEffect(() => {
+		onProps(newCompinedProps);
+	});
+
+	useEffect(() => {
+		setImage(
+			<ImageComponent
+				{...newCompinedProps}
+				style={[
+					style,
+					{
+						width: scalableWidth,
+						height: scalableHeight,
+					},
+				]}
+			/>
+		);
+	}, [scalableHeight, scalableWidth]);
+
+	const onProps = (localProps) => {
+		const {source} = localProps;
+		if (source.uri) {
+			const sourceToUse = source.uri ? source.uri : source;
+
+			Image.getSize(
+				sourceToUse,
+				(width, height) => adjustSize(width, height, newCompinedProps),
+				console.err
+			);
+		} else {
+			const sourceToUse = resolveAssetSource(source);
+			adjustSize(sourceToUse.width, sourceToUse.height, newCompinedProps);
+		}
+	};
+
+	const adjustSize = (sourceWidth, sourceHeight, localProps) => {
+		const {width, height} = localProps;
+
+		let ratio = 1;
+
+		if (width && height) {
+			ratio = Math.min(width / sourceWidth, height / sourceHeight);
+		} else if (width) {
+			ratio = width / sourceWidth;
+		} else if (height) {
+			ratio = height / sourceHeight;
+		}
+
+		if (mounted.current) {
+			const computedWidth = sourceWidth * ratio;
+			const computedHeight = sourceHeight * ratio;
+
+			setScalableWidth(computedWidth);
+			setScalableHeight(computedHeight);
+
+			onSize({width: computedWidth, height: computedHeight});
+		}
+	};
+
+	if (!onPress) {
+		return image;
+	} else {
+		return <TouchableOpacity onPress={onPress}>{image}</TouchableOpacity>;
+	}
 };
 
 ScalableImage.propTypes = {
-    width: PropTypes.number,
-    height: PropTypes.number,
-    onPress: PropTypes.func,
-    onSize: PropTypes.func,
-    background: PropTypes.bool,
-};
-
-ScalableImage.defaultProps = {
-    background: false,
-    onSize: size => {}
+	width: PropTypes.number,
+	height: PropTypes.number,
+	onPress: PropTypes.func,
+	onSize: PropTypes.func,
+	background: PropTypes.bool,
 };
 
 export default ScalableImage;


How to Apply the Patch

  1. Install patch-package:
npm install patch-package
  1. Add the postinstall script in your package.json to apply patches automatically after installing packages:
{
  "scripts": {
    "postinstall": "patch-package"
  }
}
  1. Create the Patch File:

Save the above patch file content in a file named react-native-scalable-image+1.1.0.patch in the patches directory of your project.

  1. Run npm install:

This will automatically apply the patch.

By following these steps, you can resolve the deprecation warning while ensuring compatibility with future React releases.

And maybe I can make PR for this in the future.

manssorr avatar May 30 '24 23:05 manssorr

Ok I've added the patch file but I'm getting an error that it could not be parsed. react-native-scalable-image+1.1.0.patch

yarn install v1.22.22
[1/4] Resolving packages...
success Already up-to-date.
$ patch-package
patch-package 8.0.0
Applying patches...
[email protected] ✔

**ERROR** Failed to apply patch for package react-native-scalable-image

  This happened because the patch file patches\react-native-scalable-image+1.1.0.patch could not be parsed.

  If you just upgraded patch-package, you can try running:

    cd patches\react-native-scalable-image+1.1.0.patc
    patch -p1 -i h
    npx patch-package react-native-scalable-image
    cd ../..

  Otherwise, try manually creating the patch file again.

bruce-mec avatar Aug 03 '24 11:08 bruce-mec

Fixed! Turned out to be a CRLF vs LF issue in the file Patch Package Issue #191

Corrected file if anyone needs it: react-native-scalable-image+1.1.0.patch

bruce-mec avatar Aug 03 '24 11:08 bruce-mec