Skip to content

[dashboard] lint warnings: NewProject.tsx #8995

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

Closed

Conversation

trumbitta
Copy link
Contributor

Description

As per https://discord.com/channels/816244985187008514/885406100436951080/953232219261009950

This fixes the first bits of lint warnings.

Specifically:

  • adds ESLint and Prettier to the auto-installed VSCode extensions
  • activates format on save for TypeScript and JavaScript
  • adds a .gp-link Tailwind class to make buttons mimic links and avoid using <a href="javascript:void(0)" ...>
  • fixes all the linting warnings for projects/NewProject.tsx

Related Issue(s)

Re #3841

How to test

  • launch the dashboard app
  • try to create a new project: it should still work
  • look in the console logs or in the terminal: there shouldn't be any lint warning for projects/NewProject.tsx
  • if you are using VSCode, try opening a TypeScript file and check if "format on save" via the Prettier extension is working (remember Prettier won't work if there are syntax errors - red wiggles - in the file)

Release Notes

- [devx]: Added ESLint and Prettier to the auto-installed VSCode extensions
- [devx]: Activated "format on save" for TypeScript and JavaScript
- [dashboard]: Added a `.gp-link` Tailwind class to make buttons mimic anchor tags
- [dashboard]: Fixed all the linting warnings for `projects/NewProject.tsx`

Documentation

To be used for anchor tags that should've been buttons because
they don't really bring the user to any new location.
@trumbitta
Copy link
Contributor Author

trumbitta commented Mar 29, 2022

@jankeromnes this is the new #8842 🤞

Copy link
Contributor

@jankeromnes jankeromnes left a comment

Choose a reason for hiding this comment

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

Hi @trumbitta, many thanks for improving Gitpod! 🔥 (and also for your patience on our code reviews 😇)

I really like most of the changes proposed here, and think they are quite valuable improvements. 👍

But, since I'm a bit uncertain about a few items, I've left some questions/remarks in-line. Please take a look at them when you have some time, I'm looking forward to your thoughts on these.

@@ -42,6 +42,29 @@ export default function NewProject() {

const [authProviders, setAuthProviders] = useState<AuthProviderInfo[]>([]);

const updateReposInAccounts = useCallback(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it really necessary to use useCallback here? I believe we haven't used it elsewhere in the dashboard yet, and if I understand it correctly, calling updateReposInAccounts from the Effect with the dependency selectedProviderHost already ensures that we call it only once every time the dependency changes.

I think I'd prefer not using this feature here, to limit the "magic" in our code. What do you think? 🙂

Copy link
Contributor Author

@trumbitta trumbitta Mar 31, 2022

Choose a reason for hiding this comment

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

Oh it was actually a cascading effect 🙂

  • Without the useCallback, we have this linting warning: "The 'updateReposInAccounts' function makes the dependencies of useEffect Hook (at line 203) change on every render. To fix this, wrap the definition of 'updateReposInAccounts' in its own useCallback() Hook"
  • Leaving updateReposInAccounts out of the dependencies of that useEffect to silence the previous warning, we have this other warning: "React Hook useEffect has a missing dependency: 'updateReposInAccounts'. Either include it or remove the dependency array."
  • Removing the dependency array altogether to silence the previous warning, of course makes the hook execute on every render, while keeping it empty generates the linting warning about not having empty dependency arrays when we are using some dependencies inside the hook.

The only alternative seems to be silencing the ESLint rule for this line, but as long as the code still works as intended I'd rather follow the lead of the linting rules and move on.

Let me know what you want me to do!

Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm not mistaken, you've already added the updateReposInAccounts closure as a dependency to the useEffect. Is that not enough to resolve the warning? (I.e. without needing the extra useCallback?)

Copy link
Contributor

@jankeromnes jankeromnes Mar 31, 2022

Choose a reason for hiding this comment

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

Or, actually I really don't like this pattern of implementing functions that are only called once (EDIT: to clarify, this is a pre-existing problem from before your Pull Request, not something you did here). What about moving all the updateReposInAccounts code back inline into the useEffect? (Maybe as an in-line async function if needed.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about moving all the updateReposInAccounts code back inline into the useEffect? (Maybe as an in-line async function if needed.)

Oh that's also my usual first move 🤝 but in this case updateReposInAccounts is also used elsewhere outside the useEffect.
Avoidable? Probably yes, but I think it will come with future refactorings 🔮

Copy link
Contributor Author

@trumbitta trumbitta Mar 31, 2022

Choose a reason for hiding this comment

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

If I'm not mistaken, you've already added the updateReposInAccounts closure as a dependency to the useEffect. Is that not enough to resolve the warning? (I.e. without needing the extra useCallback?)

Yes, but we have another warning :D look at the first of my bullet points above:

Without the useCallback, we have this linting warning: "The 'updateReposInAccounts' function makes the dependencies of useEffect Hook (at line 203) change on every render. To fix this, wrap the definition of 'updateReposInAccounts' in its own useCallback() Hook"

Copy link
Contributor Author

@trumbitta trumbitta Mar 31, 2022

Choose a reason for hiding this comment

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

That's because without useCallback the function gets created on every render, and that triggers the dependency array of the useEffect

@@ -69,7 +92,7 @@ export default function NewProject() {
window.history.replaceState({}, "", window.location.pathname);
setSelectedTeamOrUser(user);
}
}, []);
}, [location.search, teams, user]);
Copy link
Contributor

@jankeromnes jankeromnes Mar 31, 2022

Choose a reason for hiding this comment

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

I'm not 100% sure whether this change makes sense:

  • Currently, we only call this effect once, and we immediately "consume" the search parameter if found (i.e. if you visit /new?team=1234, we immediately select team 1234 and overwrite the URL to /new without the query parameter). This means that, if we call this code multiple times, only the first time can have any effect.
  • Calling it again if location.search changes sort of makes sense, but can it really happen that location.search changes without a reload? (I guess it could happen if we have something like <Link to="/new?team=1234"/> 🤔)
  • Can teams or user really change here? If teams or user can be something unexpected, I guess we'd need to check for that in the beginning of the effect, and return early if the values are unexpected (e.g. undefined or empty array?)

All in all, since this code currently seems to work in all cases, I'm a bit hesitant to change the effect logic here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I totally get it: this is a classic situation and it happens frequently when you start paying attention to ESLint rules.

My current stance about it, as you can infer from the proposed changes, is to just let ESLint do its thing and use its auto-fix feature: since the resulting code is basically always equivalent to what it was before the auto-fix, the auto-fixed dependency array quickly becomes like an implementation detail of sorts, I'm positive that ESLint has my back, and I can focus on the real features I need to work on.

Again, let me know what you want me to do :)
These are decisions I'm going to respect in all the future PRs about the linting warnings ✅

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks! I generally agree with you, but I believe I had one bad experience where I just followed ESLint and it broke my component 😬 (or, maybe the bug was my fault and I now wrongly blame ESLint for it). I guess this calls for more testing. 👀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it happened to me once!
I don't remember the specifics but like you said turns out it was my "fault" meaning I then applied "more React" to the problem (IIRC more composition and maybe a custom hook 🤔 ) and that fixed both the warning and the bug 🐞

@@ -166,30 +213,10 @@ export default function NewProject() {
await getGitpodService().server.triggerPrebuild(project.id, null);
})();
}
}, [project, sourceOfConfig]);
}, [guessedConfigString, project, sourceOfConfig]);
Copy link
Contributor

Choose a reason for hiding this comment

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

Reading the code, I think depending on guessedConfigString in addition to sourceOfConfig has the same effect. No objection here if it makes the linter happy. 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for this ❤️ I've been wanting to have this team-wide for a long time.

@trumbitta
Copy link
Contributor Author

trumbitta commented Apr 5, 2022

🎶 And we're back! 🎶 Welcome to this new episode of "Weekly pings to @jankeromnes!"

💖

Hey, any news? I see we also managed to wait long enough for the usual merge conflicts to show up 🤣

@jankeromnes
Copy link
Contributor

jankeromnes commented Apr 5, 2022

Hi @trumbitta! Thank you again for all these improvements, and for keeping up the pings to make sure that they get the attention they very much deserve.

Most of your changes are actually fine and could be merged as is, but I'm very nervous about the effect dependency changes, so I would like to spend more time investigating & testing those specifically.

(On a side note, if this had been a few separate Pull Requests, I believe I could have approved and merged most of them, while only needing more time for reviewing the effect dependency changes. 💭)

@trumbitta
Copy link
Contributor Author

trumbitta commented Apr 5, 2022

No problem, how do you want me to split them?

I can close this one and open the new ones. 🤝

@stale
Copy link

stale bot commented Apr 16, 2022

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the meta: stale This issue/PR is stale and will be closed soon label Apr 16, 2022
@trumbitta
Copy link
Contributor Author

Unstale

@stale stale bot removed the meta: stale This issue/PR is stale and will be closed soon label Apr 16, 2022
@geropl geropl added the team: webapp Issue belongs to the WebApp team label Apr 21, 2022
@trumbitta
Copy link
Contributor Author

trumbitta commented Apr 29, 2022

Hey 😊

I think I'm going to close this and redo everything bit by bit (see #9269 and #9641), with the tiniest possible PRs while @gtsiolis drinks wine and smiles at my general direction, because the plan we hatched with @geropl on https://discord.com/channels/816244985187008514/953232219261009950/953667195089588305 didn't stand the test of time 👴

@trumbitta trumbitta closed this Apr 29, 2022
@gtsiolis
Copy link
Contributor

gtsiolis commented Apr 29, 2022

@trumbitta 🙂
6ear4m

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants