-
Notifications
You must be signed in to change notification settings - Fork 14
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
Redux cleaning #550
Redux cleaning #550
Conversation
* Separate History from Redux * Update References to History * Remove connected-react-router * Update Location Usage Co-authored-by: Matei-Alexandru Gardus <[email protected]> Co-authored-by: Steven Steiner <[email protected]>
This is some great work, @yesean, well done! I've looked over your PR at a first glance, and overall, it's good! I haven't reviewed the business logic you've changed yet, but I'll probably do that after finals week. I think there's a couple questions that came up while I looked over it we might want to discuss:
What do y'all think of this? |
Ah sorry I've been MIA for the past week(s) about this, you can completely ignore the |
const EditEventCustomForm = (EditEventForm as unknown) as React.ComponentClass<any>; | ||
const EditEventCustomForm = EditEventForm as unknown as React.ComponentClass<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine for now, I opened #551 which I think will address some of the weird Typescript casting we have throughout the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That must've come from prettier
, I don't recall manually editing that. as
is probably left associative so the parenthesis don't matter.
@@ -64,4 +63,4 @@ const FormikCreateEventForm = withFormik({ | |||
}, | |||
})(CreateEventForm as React.FC); | |||
|
|||
export default connect(null, { postEvent, copyLink })(FormikCreateEventForm); | |||
export default connect(null, { postEvent })(FormikCreateEventForm); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you addressing all instances of connect(
in this PR? You mention this in your second point, but I'm still seeing instances of it in use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only instances where I left connect
was with Formik since there isn't a way to access the useDispatch
or useSelector
hooks with the withFormik
HOC. In order to remove the connect
usage there, we'd have to rewrite the Formik code with Formik hooks or different component APIs which is probably better suited for another PR.
import './style.less'; | ||
import { verifyEmail } from '../../utils'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we keep import './style.less';
as the last import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For every file that I modified, I ran Typescript's built in organizeImports
command from the language server tsserver
. I'm not sure if we can configure it, but I like having an automated, opinionated formatter for imports.
import './style.less'; | ||
import { sendEmailVerification } from '../../utils'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -1,50 +1,32 @@ | |||
import React, { useEffect } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes in this, requireAuth
, and requireStoreAccess
will need to be re-applied to Paul's new access protection component. We'll want to merge from master to incorporate those changes.
<NavTileItem icon={DashboardIcon} text="Dashboard" /> | ||
<NavTileItem icon={DashboardIcon} /> | ||
</NavLink> | ||
<NavLink activeClassName="selected" to="/leaderboard"> | ||
<NavTileItem icon={LBIcon} text="Leaderboard" /> | ||
<NavTileItem icon={LBIcon} /> | ||
</NavLink> | ||
<NavLink exact activeClassName="selected" to="/profile"> | ||
<NavTileItem icon={ProfileIcon} text="Profile" /> | ||
<NavTileItem icon={ProfileIcon} /> | ||
</NavLink> | ||
<NavLink activeClassName="selected" to="/discord"> | ||
<NavTileItem icon={DiscordIcon} text="Discord" /> | ||
<NavTileItem icon={DiscordIcon} /> | ||
</NavLink> | ||
{isAdmin && ( | ||
<NavLink activeClassName="selected" to="/admin"> | ||
<NavTileItem icon={AdminIcon} text="Admin" /> | ||
<NavTileItem icon={AdminIcon} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do these changes tie in to redux stuff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The text
prop was unused in the NavTileItem
component so I removed it. I think it came up when I was resolving lint warnings.
const cart = JSON.parse(serializedCart); | ||
return cart as Cart; | ||
} catch (err) { | ||
return {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we console.log for store, shouldn't we do the same for load? And perhaps it should be a notify
so that the user sees that where was an error and it's not a mystery why something didn't save/load.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I was planning on removing the log and doing what loadCart
does. But I like the idea of adding a notify
so something like:
try {
// ...
} catch (err) {
notify(err);
return {};
}
// ...
Does that sound good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some nits for any things Steven didn't mention that I thought would be important but otherwise, before we merge, I feel like we should still discuss the items I mentioned in my first comment before we merge.
src/admin/adminSlice.ts
Outdated
@@ -0,0 +1,36 @@ | |||
/* eslint-disable no-param-reassign */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The no-param-reassign
rule in our eslint config has the option {props: true}
(from airbnb) which forbids mutating properties of parameters to reduce side effects. However, since redux-toolkit
uses immer for createSlice
, it's more idiomatic to mutate the state
argument when defining reducers since it'll be equivalent to copying the parameter and is generally easier to read as well. I still think it's a good rule, so I've just disabled it in all slice files since createSlice will usually mutate the state parameter.
redux-toolkit
has a discussion on this which tldr: airbnb is too restrictive, just use {props: false}
which is the eslint default anyway.
Thoughts?
import React, { useState, ChangeEventHandler, FocusEventHandler, FormEventHandler } from 'react'; | ||
import { AutoComplete, Checkbox, Form, Input, Button, Tooltip, Tag, Icon, Select } from 'antd'; | ||
import { AutoComplete, Button, Checkbox, Form, Icon, Input, Select, Tag, Tooltip } from 'antd'; | ||
import React, { FormEventHandler, useState } from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically, I think in React the 'react' import should always be first in file (unless you're in Next.js, where you don't need it). I might wrong on this, and CRA might have removed that need. We should readjust that in files where it happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above. I don't believe the react import needs to come first, but it may be more idiomatic. Also, I think you're referring to the new JSX Transform where the React
import is not needed and JSX completely handled at compile time. Unless we need to use React 16.3, we could upgrade to 16.4 or 17 to take advantage of it. Facebook even provides a codemod to automatically remove the unneeded imports. All we'd have to do is upgrade react
and react-scripts
I believe.
I don't really see the distinction between API calls and business logic as API calls feel like another step in the logic. Moreover, the calls are generally localized to a section of the store and not shared between sections, so to me, it makes sense to keep them at a section-level rather than the top-level. Perhaps,
|
Just to recap all the discussion from above and meetings:
|
Fixed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally looks good to me! 🚀 👀
Redux Cleaning (#550) fails to run at production while containing too many file changes to individually bug fix and address. Thus, a decision was made to revert this commit and all commits after this commit was made.
Redux Cleaning (#550) fails to run at production while containing too many file changes to individually bug fix and address. Thus, a decision was made to revert this commit and all commits after this commit was made.
This PR is a refactor of our redux usage, most notably the help of redux-toolkit. The main goal was to simplify the code and reduce the amount of boilerplate brought on by redux. This is achieved in multiple ways:
createSlice
andcreateAsyncThunk
to define redux reducers and actions. These helper functions reduce a lot of redux code (with the help of immutable-js and typescript) which allows all of the redux to be colocated into a single*Slice.ts
file.connect
HOC with theuseDispatch
anduseSelector
hooks which effectively remove the need for most container components.Addtional notes:
*{Reducer,Actions,Types}.ts
files have been replaced with*Slice.ts
and autils.ts
. the slice file holds all of the redux logic and the utils file holds the non-redux logic (fetching, notifying, etc). generally, the functions in utils are imported into the slice to provide any needed redux for the utility. this was done to decouple the redux and non-redux logic as much as possible.redux_reducers.ts, combineReducers, createStore
setup has been replaced with the simplerredux/store.ts, configureStore
(the toolkit recommended way)Awaited
utility type which was introduced in Typescript 4.5 so I upgraded the typescript package to latest. Unfortunately, typescript changed their AST in 4.0 butcreate-react-app
uses an older, incompatible version oftypescript-eslint/parser
so I used selective dependency resolutions (resolutions
inpackage.json
) to force the new version of the eslint parser. Nevertheless, everything is working fine now, though this change may be better suited for another PR?