/RFTB2019_GitHub_Finder

The first Project in Brad Traversy's React Front To back 2019 course branched for students

Primary LanguageJavaScript

RFTB2019 GitHub Finder

The first project in Brad Traversy's React Front to Back 2019 Udemy course.

The master branch is the final completed project from the course.

I have refactored the app to take a more hook friendly context approach.

I think Brad at the time of the course tried to substitute life cycle methods with the closest hooks approximation which is understandable and I see a lot of tutorials and courses doing much the same. Hooks were very new at the time of recording, however hooks require a completely different approach and thought process really. We need to think in terms of hooks and functions and not life cycle.

If you're looking at this branch and wondering why in the course we had to use // eslint-disable-next-line or thought this doesn't feel right ignoring the linting rules, then I urge you to have a read of this post on overreacted by Dan Abramov. It covers a lot more than just useEffect

There is also this great article from Kent C. Dodds which covers the issues we had in this course very well.

To summarize the issues we faced in the course though, and why we had to use // eslint-disable-next-line at all is that all our data fetching methods are in our context state (GitHubState.jsx) and passed down to all our components via the Provider. The problem with this is that every time we update our context state we create a new function inside the GitHubState component.

Functions being reference types are unique in memory so every time we update our state React invokes our GitHubState component/function again and we create new functions in the component. If we include one of those functions in a dependency array it will trigger a useEffect as the function changes every time because it's a new function, in memory it's not the same function even though it may have the same code and do the same thing and even be named the same. So if we include these functions in our useEffect dependency array (as the linter suggests) in User.jsx then each time we fetch data and our reducer runs it updates the context which triggers a re-render (creating a whole set of new functions). The useEffect dependency sees it as a new function and triggers another render which again updates the state when we call the function in our useEffect, which triggers another re-render and so on.... infinite loop of re-rendering.

The solution is not to add an empty array and tell the linter to ignore it (trying to make a componentDidMount out of useEffect), but to think in terms of hooks and functions.

so...

  1. Take all our fetching data methods out of GitHubState to keep them pure and not re-create a new function on each render/update actions.js.
  2. return the promise from our data fetching methods.
  3. Only pass down our dispatch from our GitHubState Provider (React guarantees that our dispatch returned from useReducer is static and won't change) GitHubState.jsx.
  4. Import the data fetching method we need in the component we need it, call that function in a component level useEffect and then dipsatch from our component User.jsx.

This cleans up our app considerably, follows the good advice from the react guidelines/linter, improves the quality and readability of our code and now we are thinking in terms of hooks and functions.

Updates since course published

Since the course was published, GitHub has ceased authentication via URL query parameters You can get an access token by following these instructions For this app we don't need to add any permissions so don't select any in the scopes. DO NOT SHARE ANY TOKENS THAT HAVE PERMISSIONS This would leave your account or repositories vulnerable, depending on permissions set.

On this branch you can see how to use the generated token in /src/context/github/actions.js

You'll also need to change up your .env.local file to include

REACT_APP_GITHUB_TOKEN='token <your_no_permissions_token_here>'

React Router updated to version 6

React Router Dom V6 introduced some breaking changes. Instead of <Switch /> we now use <Routes /> In place of a component prop on our <Route /> we now no longer pass a component but an element with an element prop. There is also no longer an exact prop. Most of the changes can be seen in App.jsx and in User.jsx.

You can read the full migration guide in react-router docs https://reactrouter.com/docs/en/v6/upgrading/v5

Some notes before you deploy

For the environment variables we set in the Netlify UI to be used we need to let Netlify run the build which as far as I know only works if you deploy from GitHub. If we run npm run build then netlify deploy --prod as per lesson 5-35 we are running the build on our local machine.

Additionally any environment variable we set needs to be prefixed with REACT_APP_, even for deploying to Netlify. process.env.NODE_ENV allows us to check the the environment (develpment in dev server and production in build).

You cannot override NODE_ENV manually

create-react-app docs for further reading

The environment variables only prevent your keys from being shared in your GitHub repo, anyone who inspects the code or looks at the network requests will see your keys, they're not private unless the server is making the API requests, not our client side app. So this may be something you would want to be aware of going into production with your own projects. So even if we do set up continuous deployment from GitHub to Netlify our keys will be available after Netlify runs the build.

To install and run locally

Clone the repo

git clone https://github.com/bushblade/RFTB2019_GitHub_Finder.git

Change into directory project

cd RFTB2019_GitHub_Finder

install

npm i

Run the dev server

npm start

Build the project

npm run build