Skip to content

Commit

Permalink
Merge pull request Expensify#24159 from kowczarz/16164-migrate-image-…
Browse files Browse the repository at this point in the history
…index-js-to-function-component

Migrate Image/index.js to function component
  • Loading branch information
marcaaron authored Aug 9, 2023
2 parents 07571e3 + 241b5b0 commit 39e4ca2
Showing 1 changed file with 35 additions and 47 deletions.
82 changes: 35 additions & 47 deletions src/components/Image/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useEffect, useMemo} from 'react';
import {Image as RNImage} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
Expand All @@ -7,76 +7,64 @@ import ONYXKEYS from '../../ONYXKEYS';
import {defaultProps, imagePropTypes} from './imagePropTypes';
import RESIZE_MODES from './resizeModes';

class Image extends React.Component {
componentDidMount() {
this.configureOnLoad();
}

componentDidUpdate(prevProps) {
if (prevProps.source === this.props.source) {
return;
}
this.configureOnLoad();
}

function Image(props) {
const {source: propsSource, isAuthTokenRequired, onLoad, session} = props;
/**
* Check if the image source is a URL - if so the `encryptedAuthToken` is appended
* to the source.
* @returns {Object} - the configured image source
*/
getImageSource() {
const source = this.props.source;
let imageSource = source;
if (this.props.isAuthTokenRequired) {
const source = useMemo(() => {
if (isAuthTokenRequired) {
// There is currently a `react-native-web` bug preventing the authToken being passed
// in the headers of the image request so the authToken is added as a query param.
// On native the authToken IS passed in the image request headers
const authToken = lodashGet(this.props, 'session.encryptedAuthToken', null);
imageSource = {uri: `${source.uri}?encryptedAuthToken=${encodeURIComponent(authToken)}`};
const authToken = lodashGet(session, 'encryptedAuthToken', null);
return {uri: `${propsSource.uri}?encryptedAuthToken=${encodeURIComponent(authToken)}`};
}

return imageSource;
}
return propsSource;
}, [propsSource, isAuthTokenRequired, session]);

/**
* The natural image dimensions are retrieved using the updated source
* and as a result the `onLoad` event needs to be manually invoked to return these dimensions
*/
configureOnLoad() {
useEffect(() => {
// If an onLoad callback was specified then manually call it and pass
// the natural image dimensions to match the native API
if (this.props.onLoad == null) {
if (onLoad == null) {
return;
}

const imageSource = this.getImageSource();
RNImage.getSize(imageSource.uri, (width, height) => {
this.props.onLoad({nativeEvent: {width, height}});
RNImage.getSize(source.uri, (width, height) => {
onLoad({nativeEvent: {width, height}});
});
}
}, [onLoad, source]);

render() {
// Omit the props which the underlying RNImage won't use
const forwardedProps = _.omit(this.props, ['source', 'onLoad', 'session', 'isAuthTokenRequired']);
const source = this.getImageSource();
// Omit the props which the underlying RNImage won't use
const forwardedProps = _.omit(props, ['source', 'onLoad', 'session', 'isAuthTokenRequired']);

return (
<RNImage
// eslint-disable-next-line react/jsx-props-no-spreading
{...forwardedProps}
source={source}
/>
);
}

return (
<RNImage
// eslint-disable-next-line react/jsx-props-no-spreading
{...forwardedProps}
source={source}
/>
);
}
function imagePropsAreEqual(prevProps, nextProps) {
return prevProps.source === nextProps.source;
}

Image.propTypes = imagePropTypes;
Image.defaultProps = defaultProps;

const ImageWithOnyx = withOnyx({
session: {
key: ONYXKEYS.SESSION,
},
})(Image);
const ImageWithOnyx = React.memo(
withOnyx({
session: {
key: ONYXKEYS.SESSION,
},
})(Image),
imagePropsAreEqual,
);
ImageWithOnyx.resizeMode = RESIZE_MODES;
export default ImageWithOnyx;

0 comments on commit 39e4ca2

Please sign in to comment.