This is an example project that showcases React/Redux to sort Github issues.
Goals of the application:
- Provide interface to login with
apiKey
- Save apiKey into localstorage (to allow subsequent visits without re-logging in)
- Fetch repositories of current user
- See issues related to each repository
- Set a custom order of issues (and fallback to default order)
- Persist said order to local browser storage
- Grab a Github API personal access token
- Copy the token to your clipboard
yarn
andyarn start
- Login with your given token.
- On Github, make sure you have at least one repository with at least 2 issues to properly showcase the application demo.
- Copy
.env-example
to.env
in the project root, updating parameters if necessary. yarn
yarn start
We are using husky
to enforce the linting rules before committing. Invalid lint rules will attempted to be fixed if found, and prevented from being committed.
yarn test
This is a high level view of the notable files and directories in this application:
├── .eslintrc.js -> custom eslint config
├── .env -> app environment
├── .prettierrc -> prettier config
├── api -> api singleton (uses `axios`)
├── components -> shared components
├── containers -> app containers
├── index.js -> app entry and render call
├── index.scss -> global styles (mostly resets)
├── reducers -> application redux reducers (and action creators)
├── selectors -> redux store selectors
├── store -> redux store configuration and helpers
└── styles -> shared styles
The general pattern held here is that those files in containers
will hold the mapStateToProps
assignments only, and pass down to other containers.
We have top level keys to store the data for the user
, repo
, and issue
items, which in turn tend to correspond to an API resource.
The most complex area of this application is likely in the onSetOrder
action creator found in the reducers/issue
. This action creator takes an array of sorted items (provided by react-beautiful-dnd
's callback and a simple function to rearrange the items) and modifies the reducer to apply an order based on the name
of the repo.
For example:
dispatch(setOrder({
name: 'some-repo',
issues: [{
id: 123
...
}, {
id: 252
...
}])
})
...will modify the issue
reducer to something like:
state.issue.order = {
'some-repo': {
123: 0,
252: 1,
},
};
In turn we have a selector that will iterate through these key based values and return its proper sort order:
// sortIssues selector
...
return state.issue.order[name][a.id] < state.issue.order[name][b.id] ? -1 : 1;
...
This is one of the more notably complex behaviors in this project.
- More robust selectors
- Reducer Tests