# Debugging Tips & Tricks
## Quick Tips
These will minimize the time you spend debugging by making it more contained, controlled, and targeted. Understanding the problem _before_ trying to fix it.
### Tip 1: Small Steps
JPFP runs in "tiers", and lots of "real world" projects are similar - the app is broken down into features. Sometimes a single feature may stretch across the whole stack (backend route, front end view, front end data management, styling, etc).
**Do 1 feature at a time**. And better yet - break that feature down into even _smaller_ pieces, and **do 1 piece of a feature at a time**.
At each step of the way, make sure you are:
- Testing each step before moving on to the next one. Is it doing exactly what you want it to?
- Committing your code
Small steps reduces your debugging time by A LOT. When a bug comes up - you know exactly which small piece of code you just edited, so you know where to look first.
### Tip 2: Read your console ALL THE TIME
There are SO many helpful logs in your console at all times, _especially_ when things are going wrong.
**ALWAYS have your consoles open**: that means the server-side console, AND the browser-side console.
Never open your app without the console open.
### Tip 3: Decipher your error messages. Read the whole thing. Break it down. Investigate.
- **Read errors in the order they happened**: Errors are logged from _top to bottom_. The first error that occured will be the highest up in your console, and every error that happened afterwards will follow.
- **Read the error message... carefully**: This is the first line of each new error. Not every error message is super clear on what the problem is, but it offers valuable hints. Pick out the variables it's talking about, or the specific type of error it's giving. Think about which pieces of code you just wrote that may have to do with what the error is mentioning. _(See below for some common errors and how to debug them)._
- **Read the stack trace... very carefully**: The stack trace comes immediately after the message, and reads from top to bottom. The top of the stack trace shows the code that was called first (which is likely the code _you_ wrote), and then each piece of code that was called after (likely library code). Read through the stack trace and see if you can find a line of code referenced that _you_ wrote. Then (especially if you don't see a line you wrote), keep reading. You don't need to look into library source code, but what libraries are listed in the stack trace? Are they Redux-related? Sequelize? The libraries listed will give you more hints about what went wrong, and where to look.
If something isn't working, **NEVER EVER EVER** just go straight to your code. **ALWAYS** open up the console and read the error in detail.
Jumping straight into the code will leave you poking around aimlessly in your code: you may edit things that aren't broken, leaving you more confused, and you'll generally spend _more time_ debugging, than if you put in the time upfront to read the error. The more info you gather from the error - the more _focused_ and relevant your debugging will be - and the less time you'll spend debugging.
## Common errors and how to debug them
These errors come up frequently. I won't tell you exactly how to fix them all, but I'll break down what they mean, and approaches you can take to fix it.
### `cannot read property 'map' of undefined`
Where are you calling "map"? Whatever you're calling "map" on is undefined. "But I'm getting the data!", you say. That may be true for some part of your code, but it's not here in this part of the code. The code never lies ;) - never make assumptions. **Check. Everything.**. _Why_ is the data undefined here? Here's some questions to consider to solve this mystery:
- Did your component mount yet? Are you sure? Put a log in there.
- Is the data being populated in Redux? Are you sure? Check the logs.
- Are you bringing the right data into your component? Are you sure? Log the props before rendering.
- Does the data you're trying to render _actually look the way you think it does?_ Are you sure? Examine the data in the console and compare what's there to how you're accessing it's values in your code. Do they match up?
Another tip here is to make sure you have an initial state set up. An empty object, array, or string is going to be better for your code than "undefined". `[].map` is valid, after all... `undefined.map` is not.
### Errors like "reducer must be a function" or "must be a component"
Most often, errors like this are from incorrect imports/exports. You may have written your reducer as a function, just as you should. But then you imported it wrong:
- Are you sure you exported what you need? Double check.
- Check the file path of the import. Is it the right location?
- Is it the default export? Then the import _does not have curly braces_.
- It is a named export? Then the import _must be in curly braces, and imported with the exact same name as it was exported_.
### 404 Not Found for a route you write code for... but it's not finding it
Most likely, this is a router mounting issue. Trace the flow of an incoming request to your Express server. Check which routers are _already mounted_, and where. You may have written code for a route whose path is actually `/api/candies/candies`, so when you try to make a request for `/api/candies`, it's a 404.
- Start at the "beginning" of your server... where is the app being created? (Look for the line with `const app = express()`).
- Follow the routers. If you're looking for what happens with a request for `/api/candies`, start at the beginning, and follow line by line. Don't assume - read each line carefully - will this route/middleware match the current request?
- Log it out. Add logs to your routes, and be specific in the string printed out. If you see the log, you're hitting that route. If not... more debugging.
### A change is persisting in your backend, but you can't see the change on the frontend without refreshing the page
This is usually a Redux issue:
- After the API call in your thunk, are you dispatching another action?
- Are you awaiting the API call?
- Is your API call sending a response? What is it?
- Check the reducer: are you changing the state correctly? Are you sure? Log it out to double check.
- Are your component props mapped correctly to your Redux state? Log them out and double check.
### Not seeing changes to the code you wrote appear when running the app
Check how you're running it. Are you running a command that **watches for changes** on BOTH the backend and frontend? Look for these in the package.json:
- A server that's "watching" will likely have `nodemon` in the command
- A client that's "watching" will likely have a `-w` flag when it runs webpack
- If you do NOT have these things happening, then your server is not restarting, or your client is not rebundling, so you're viewing stale code.
- If the issue persists, sometimes a good restart can help ;)
## Handy tricks and tools
Keep these things in mind while you're debugging and testing out your code. They'll help you form a fuller picture/understanding of what's going on in your app
### Helpful Tools
- **Postman**: use this to check your API routes. You can make all types of HTTP requests (GET, POST, etc)
- **React Dev Tools**: use this to check which components are currently being displayed on your page. You can find it in the browser dev tools as one of the tabs. This tool also shows you the props for each component!
- **Redux Logger** or **Redux Dev Tools**: use this to check your Redux store state, the actions that flow into your reducer, and how each of those actions change the state.
- **JSONView Chrome Extension**: pretty-print any raw JSON your browser tries to display (for instance, if you navigate to `localhost:1337/api/candies` and raw JSON data is displayed - this extension will format it nicely).
- **Postico** or **pgAdmin**: use this to check what's in your database at any point in time.
- **CONSOLE**: always have this open, for both server-side, and browser-side.
### Logging Tricks
#### To check the Redux state:
```js
const mapStateToProps = state => {
// LOG THE REDUX STATE HERE
console.log('this is the WHOLE state in redux', state);
// can help you figure out what the state looks like and how to map it to your props
}
```
#### To check that your reducer is doing what you want:
Check the Redux logger!
Also to "make" it fire, you could try manually dispatching things to your store:
```js
// in the file where your store is created:
store.dispatch(myActionCreator());
store.dispatch(myThunkCreator());
// these dispatches will trigger the Redux logger, so you can see exactly what these actions are doing in your reducer!
console.log('you can also check the state at any point too', store.getState())
```
**NOTE**: make sure to _remove_ those lines above once you start connecting your components to Redux. These manual dispatches are _just for debugging_, but should be removed once you're done checking.
#### See what props your component is getting:
Log out your props _in the render method_ - if you have a `componentDidMount` that fetches data, you'll see these logs appear _twice_: once on the initial render (initial data here) and once after the component is mounted (should see "real" data here)
```js
render() {
console.log('these are my props for the <Whatever> component', this.props)
}
```
Be careful not to dismiss the log from the initial render... Your component will still use that initial data to try to render itself. And invalid operations may be present when your data is "empty" that is causing the component to fail on it's initial render. For instance, you might be trying to access a nested property (`story.author.name`) but what if "story" is just an empty object at first? `{}.author.name` will throw an error - `{}.author` will give `undefined`, and then `undefined.name` throws an error.
Common errors related to the problem above might be `cannot access property "name" of undefined` or your error might include mention of "error boundaries" in your React component (this is a hint that React is giving you... that you might want to render something _different_ when your data is "empty", than when it's "full").
#### Check that any function is indeed being called, and with the right params:
Logs! Be specific: label all your logs so you can tell them apart.
```js
componentDidMount() {
console.log('componentDidMount of <Whatever> component')
}
handleClick(myData) {
console.log('handleClick for <Whatever< component. myData param is:', myData)
}
```