Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(ui): migrate Reports to functional component and split files #11794

Merged

Conversation

agilgur5
Copy link
Contributor

@agilgur5 agilgur5 commented Sep 10, 2023

Partial fix for #9810
Partial fix for #11740

Motivation

Modifications

Follow a very similar process to #7035

  • state -> useState

  • this.props -> arguments

  • BasePage + this.queryParams -> location argument + URLSearchParams

  • componentDidMount -> useEffect

  • services.info.collectEvent -> useCollectEvent

  • saveHistory -> useEffect + historyUrl

  • Consumer -> useContext

  • merge renderReport into the main component

  • split out filters into a separate ReportsFilters component similar to CronWorkflowFilters, WorkflowFilters, etc

  • Promise chains -> async/await

  • getters and setters to regular functions

  • split out a pure function into a util file

    • to make clear that it is pure and unrelated to React state, context, etc

Also some tiny optimizations similar to #11743:

  • use named functions instead of consts assigned to anonymous functions
    • this makes tracing a bit easier and source maps a bit clearer
    • (also technically a memory improvement as well)

Verification

  • Pure refactor, no real semantic changes
  • Test manually, seems to work, still very interactive with fancy animations
    • It was my first time using this page though, I literally didn't know it existed 👀
      • I believe it's not really documented either?
    • Screenshot below of it working:
      Screenshot 2023-09-10 at 5 19 54 PM

- follow a very similar process to 25e1939
  - `state` -> `useState`
  - `this.props` -> arguments
  - `BasePage` + `this.queryParams` -> `location` argument + `URLSearchParams`
  - `componentDidMount` -> `useEffect`
  - `services.info.collectEvent` -> `useCollectEvent`
  - `saveHistory` -> `useEffect` + `historyUrl`
  - `Consumer` -> `useContext`
  - merge `renderReport` into the main component
    - will move filters into a separate component in the next commit, following existing convention and the commit
- Promise chains -> async/await
- getters and setters to regular functions
- split out a pure function
  - can move this into a util file in the next commit

- also modify some comments in `cron-workflows-list`
- convert variable assigned to anonymous function to a named function
  - better practice, better tracing, less memory, etc

Signed-off-by: Anton Gilgur <agilgur5@gmail.com>
- split out pure function into its own file
  - to make clear that it is pure and unrelated to React state, context, etc

- split out `ReportsFilters` component similar to `CronWorkflowFilters`, `WorkflowFilters`, etc
  - be consistent with how all these work
  - similar to 25e1939, refactor logic to have an `onChange` function and retrieve Workflows in a top-level effect (after all state has been set)
    - and similarly add an SCSS file with the appropriate styles
      - note: this may be worth refactoring as nearly all the filters have the same styles

- refactor `ReportsFilters` logic to use async/await syntax
  - also refactor `CronWorkflowList` to use newer async/await syntax consistent with future state of codebase

Signed-off-by: Anton Gilgur <agilgur5@gmail.com>
Signed-off-by: Anton Gilgur <agilgur5@gmail.com>
Copy link
Contributor Author

@agilgur5 agilgur5 left a comment

Choose a reason for hiding this comment

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

It's possible to optimize this a bit with useCallback. And I think most of the functional components are memoizable too.

But that can be done in a follow-up optimization PR if needed, leaving as is for now for least potential breakage. It also runs pretty fast locally anyway so nbd probably.

history.push(historyUrl('reports' + (Utils.managedNamespace ? '' : '/{namespace}'), {namespace, labels: labels.join(',')}));
}, [namespace, labels]);

async function onChange(newNamespace: string, newLabels: 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.

potential useCallback optimization

Comment on lines +21 to +43
function getLabel(name: string) {
return (labels.find(label => label.startsWith(name)) || '').replace(name + '=', '');
}

function setLabel(name: string, value: string) {
onChange(namespace, labels.filter(label => !label.startsWith(name)).concat(name + '=' + value));
}

function getPhase() {
return getLabel(labelKeyPhase);
}

function setPhase(value: string) {
setLabel(labelKeyPhase, value);
}

function setWorkflowTemplate(value: string) {
setLabel(labelKeyWorkflowTemplate, value);
}

function setCronWorkflow(value: string) {
setLabel(labelKeyCronWorkflow, value);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

potential useCallback optimizations

Copy link
Member

@toyamagu-2021 toyamagu-2021 left a comment

Choose a reason for hiding this comment

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

I've double chacked functionality.

Copy link
Member

@isubasinghe isubasinghe left a comment

Choose a reason for hiding this comment

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

Looks good, no need to worry about useCallback for now imo.
Might even be slower for some functions, anyway I think the performance of the UI is not a worry for me regardless.

Oh the only exception being the swagger docs page which is unusable but yes not related to this issue.

@agilgur5
Copy link
Contributor Author

Looks good, no need to worry about useCallback for now imo. [...] anyway I think the performance of the UI is not a worry for me regardless.

Agreed, figure I'd notate it at least. I used to write fully memoized components, but I'd forgotten some of the optimizations like useCallback (since React hasn't been my day job in years). Some of those UIs I wrote in the past were impressively performant, so it can make a difference at scale (scale with respect to number of rerenders and components).

Oh the only exception being the swagger docs page which is unusable but yes not related to this issue.

Yea it freezes everytime I try to use it. I can't even run a profiler on it. It may very well be on the swagger-ui side though, or due to the size of the swagger. I have not seen this problem in other codebases though (but idr if we used different renderers or not).

@terrytangyuan terrytangyuan merged commit c6fdb03 into argoproj:master Sep 21, 2023
24 checks passed
@agilgur5 agilgur5 deleted the refactor-ui-reports-functional branch September 21, 2023 02:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants