App: [HOLD for payment 2023-07-06] [$250] Migrate ImageWithSizeCalculation.js to function component

Class Component Migration

Filenames

Task

  • We currently have some class components in our codebase that we would like to refactor to a function component.
  • Here’s a link with some general advice on how to refactor a class component to a function component: https://react.dev/reference/react/Component#alternatives
  • If you need additional guidance, please ask in #expensify-open-source
  • Test for any regressions and verify that there are no breaking changes
Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~019290e3ea81f50f59
  • Upwork Job ID: 1664694167941718016
  • Last Price Increase: 2023-06-02

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 30 (20 by maintainers)

Most upvoted comments

@conorpendergrast @NikkiWines, we can assign @getusha as they have no pending issues assigned right now.

πŸŽ€ πŸ‘€ πŸŽ€ C+ reviewed

Based on my calculations, the pull request did not get merged within 3 working days of assignment. Please, check out my computations here:

  • when @getusha got assigned: 2023-06-05 15:08:47 Z
  • when the PR got merged: 2023-06-27 01:51:36 UTC
  • days elapsed: 15

On to the next one πŸš€

@Vishrut19 this is a great thread to understand the process

https://expensify.slack.com/archives/C01GTK53T8Q/p1685727880152119

@getusha Thanks great thread!

Here is my proposal

Proposal : Migrate ImageWithSizeCalculation.js to function component #16167

Please re-state the problem that we are trying to solve in this issue.

Problem : Migrate ImageWithSizeCalculation.js to function component #16167

What is the root cause of that problem?

The root cause of the problem is that most of the things written are in class based which needs to be converted into function based as the updated ReactJS syntax.

What changes do you think we should make in order to solve the problem?

Before This is class based code:

class ImageWithSizeCalculation extends PureComponent {
    constructor(props) {
        super(props);

        this.state = {
            isLoading: false,
        };

        this.imageLoadingStart = this.imageLoadingStart.bind(this);
        this.imageLoadingEnd = this.imageLoadingEnd.bind(this);
        this.onError = this.onError.bind(this);
        this.imageLoadedSuccessfully = this.imageLoadedSuccessfully.bind(this);
    }

    onError() {
        Log.hmmm('Unable to fetch image to calculate size', {url: this.props.url});
    }

    imageLoadingStart() {
        // Return early if the image has already loaded (this can happen when uploading the same image twice on Android)
        if (this.isLoaded) {
            return;
        }
        this.setState({isLoading: true});
    }

    imageLoadingEnd() {
        this.setState({isLoading: false});
    }

    imageLoadedSuccessfully(event) {
        this.isLoaded = true;
        this.props.onMeasure({
            width: event.nativeEvent.width,
            height: event.nativeEvent.height,
        });
    }

    render() {
        return (
            <View style={[styles.w100, styles.h100, this.props.style]}>
                <Image
                    style={[styles.w100, styles.h100]}
                    source={{uri: this.props.url}}
                    isAuthTokenRequired={this.props.isAuthTokenRequired}
                    resizeMode={Image.resizeMode.cover}
                    onLoadStart={this.imageLoadingStart}
                    onLoadEnd={this.imageLoadingEnd}
                    onError={this.onError}
                    onLoad={this.imageLoadedSuccessfully}
                />
                {this.state.isLoading && <FullscreenLoadingIndicator style={[styles.opacity1, styles.bgTransparent]} />}
            </View>
        );
    }
}

After (new function based code):

import React, { useState, useRef } from 'react';
import { View, Image } from 'react-native';

const ImageWithSizeCalculation = (props) => {
  const [isLoading, setIsLoading] = useState(false);
  const isLoaded = useRef(false);

  const onError = () => {
    Log.hmmm('Unable to fetch image to calculate size', { url: props.url });
  };

  const imageLoadingStart = () => {
    // Return early if the image has already loaded (this can happen when uploading the same image twice on Android)
    if (isLoaded.current) {
      return;
    }
    setIsLoading(true);
  };

  const imageLoadingEnd = () => {
    setIsLoading(false);
  };

  const imageLoadedSuccessfully = (event) => {
    isLoaded.current = true;
    props.onMeasure({
      width: event.nativeEvent.width,
      height: event.nativeEvent.height,
    });
  };

  return (
    <View style={[styles.w100, styles.h100, props.style]}>
      <Image
        style={[styles.w100, styles.h100]}
        source={{ uri: props.url }}
        isAuthTokenRequired={props.isAuthTokenRequired}
        resizeMode={Image.resizeMode.cover}
        onLoadStart={imageLoadingStart}
        onLoadEnd={imageLoadingEnd}
        onError={onError}
        onLoad={imageLoadedSuccessfully}
      />
      {isLoading && <FullscreenLoadingIndicator style={[styles.opacity1, styles.bgTransparent]} />}
    </View>
  );
};

export default ImageWithSizeCalculation;



What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.