Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Convert GiantTrackTile to typescript #3698

Merged
merged 4 commits into from
Jul 5, 2023

Conversation

schottra
Copy link
Contributor

@schottra schottra commented Jul 3, 2023

Description

Converts GiantTrackTile to typescript / function component pattern to make it easier to work with for upcoming gated content changes.

  • Moved all propTypes to a type interface
  • Removed defaultProps. The parent component uses a helper function to generate valid default values
  • Moved one state variable (artworkLoaded) to a state hook
  • Updated a callback name to be consistent with pattern for other callbacks
  • Moved class helper functions into locally defined functions that read props from closure instead of class instance
  • Updated some child components to have properly Nullable props for a few cases where the values they received from GiantTrackTile might actually be null. The underlying code is already null-safe, the props just didn't reflect that.
  • Had to add an any cast for the overflow menu props, as TS is currently unable to correctly determine the track variant and it was becoming a hassle to try and refactor it so the checker would be happy. I don't love this, but since this component was already working and I didn't change how any of the values are passed/computed it seems like a safe cast for now.
  • Fixed type for the onExternalLinkClicked handler. I'm not sure why we do this, but that handler passes the entire event up the component stack, as opposed to the internal version which just passes a url 😅. Again, goal was to convert with minimal functional changes.

Dragons

There might be very subtle behaviors that stop working due to converting from class to functional component, or due to some of the minor changes I made.

How Has This Been Tested?

Tested on web, compared a variety of track states to the same version on staging to make sure now large regressions or inconsistencies popped up

How will this change be monitored?

Will test as part of full QA pass for this feature branch

Feature Flags

N/A

@schottra schottra changed the title Convert giant track tile Convert GiantTrackTile to typescript Jul 3, 2023
Copy link
Contributor

@dharit-tan dharit-tan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wowza tysm!!

didn't really go thru with a fine-tooth comb, maybe you could point out where the major changes were between the two files?

@schottra
Copy link
Contributor Author

schottra commented Jul 3, 2023

wowza tysm!!

didn't really go thru with a fine-tooth comb, maybe you could point out where the logic changes were between the two files?

Oh yep, I can try to add comments to the important bits. There aren't really any big logic changes.

Copy link
Contributor Author

@schottra schottra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dharit-tan Added some comments about the major things that changed in this file

actionGroupLabel: 'collection actions'
}

export type GiantTrackTileProps = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were all converted from GiantTrackTile.propTypes. However, that type just used things like object and string for some props which have more explicit types (i.e. Remix, PremiumConditions, CoverArtSizes). Pretty much anything in here that isn't a number/string/boolean is now more strongly typed.

trackId,
trackTitle,
userId
}: GiantTrackTileProps) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was originally the render function, and didn't destructure as many props because the helper functions defined on the class would read them directly from this.props. Now since we are defining the helpers inline here, they are read from closure and we need to pull more items off of props.

FeatureFlags.PODCAST_CONTROL_UPDATES_ENABLED_FALLBACK
)

const renderCardTitle = (className: string) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were all converted from class methods. They all had their direct destructuring of this.props removed in favor of reading them from closure.

/>
<div className={styles.infoSection}>
<div className={styles.infoSectionHeader}>
{renderCardTitle(cn(fadeIn))}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to add a cn() here because the helper function expects a simple string classname and fadeIn is an object with conditional classnames meant to be passed to the classnames function.

<span>
{/* prop types for overflow menu don't work correctly
so we need to cast here */}
<Menu {...(overflowMenu as any)}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't want to go down a rabbit hole of trying to fix the props definition for Menu... 😢

</div>
</div>

{isPremium && premiumConditions ? (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a check here on premium conditions to avoid rendering this section altogether. Technically I think the child component is safe if it isn't passed. But in TrackTile we follow the pattern of not rendering the section if there are no premium conditions.

<Linkify
options={{
attributes: {
onClick: (event: React.MouseEvent<HTMLAnchorElement>) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handler needed a more specific type.

}

return <p className={styles.progressText}>{messages.unplayed}</p>
Copy link
Contributor Author

@schottra schottra Jul 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might seem weird. TS was complaining that this component couldn't be used in JSX because it might return undefined. Lo and behold, it might!

The way the conditionals were structured, there's a rare chance (trackPosition.status being neither of the values we check against) we would return nothing from this function (though it shouldn't be likely), which would be an error in React.

@audius-infra
Copy link
Collaborator

Preview this change https://demo.audius.co/convert-giant-track-tile

@schottra schottra merged commit 468f848 into gated-content-updates Jul 5, 2023
@schottra schottra deleted the convert-giant-track-tile branch July 5, 2023 14:06
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants