This error was caused when I tried to locally run a server on a port that was already being used by another server that I had previously left running and forgot to turn off.
This command will show you all the process(es) running on a port and their PIDs
sudo lsof -i :3000
Kill the process by replacing <PID> with the process’ PID number
In the upload middleware, we define a key value. This key serves essentially as the image’s name in AWS, differentiating images in the list in the AWS Console. We are setting the key to the date at which the image is saved.
Multer is one of the most popular libraries for uploading files to a Node.js server. Multer is a Node.js middleware for handling multipart/form-data, which is primarily used for uploading files.
Install Multer package in your project
npm i multer
Create a form in your HTML file that will post to your server. Notice the enctype is set to multipart/form-data. Also, make sure to give your inputs names. That is how Multer finds them.
Below is a very basic application of Multer. When our form makes a post request to the root, the Multer middleware (upload.single('image')) will give us access to the inputs in the request. The middleware takes in the name of the file input from your form. In our case, we called the input image. req.file holds the file uploaded to the form. req.body holds the text inputs.
When we defined our upload middleware, we set the destination in which we want to store our file uploads from Multer. In this case, files from our form will be stored in the uploads folder. If the folder doesn’t exist, it will be created automatically.
var express = require('express')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
var app = express()
app.post('/', upload.single('image'), function (req, res, next) {
console.log(req.file, req.body);
})
Multer also allows us to customize the way that we handle file uploads.
The disk storage engine gives you full control on storing files to disk. There are two options available, destination and filename. They are both functions that determine where the file should be stored.
You append this storage property to your upload middleware
const upload = multer({
storage: storage,
});
You can also create a filter function to define which types of files you want to accept and which types of files you don’t. For example, you can set your filter to only accept .png, .jpeg., and .jpg file types.
CSS Custom Properties, or otherwise known as CSS Variables, allow us to handle dynamic values in our CSS. In the past, we had to use CSS preprocessors like Sass and Less to handle dynamic values or variables in our CSS. Now, CSS Custom Properties give us a native option that doesn’t have to be compiled and we can even access the variables in our JavaScript. You’ll get used to the weird syntax!
The process of defining and using variables is pretty similar no matter what part of the DOM you’re referencing. We will start with the root element, the body.
Define a variable by adding the two lines in front of its name (--). To reference the variable, use var(--style)
:root {
--main-bg-color: #f4f4f4;
}
body {
background-color: var(--main-bg-color);
}
Defining style variables for a div follows pretty much the same format. When you have a lot of variables, it can be helpful to separate the styles and the variables into two sections both referencing the same element.
If you don’t have that many variables, you can define and reference them within the same block.
.grid {
--gap: 20;
grid-gap: var(--gap);
}
We can get access to the style variables we defined in CSS in our JavaScript. In this example, I’m referencing the box div, compiling all of the div‘s applied styles into a variable called boxStyles and getting access to the --box-main-color CSS variable from the boxStyles array.
CSS Grid allows us to create 2 dimension layouts and align items in columns and rows.
All browsers support grid layout.
Flexbox vs. Grid
The primary difference between CSS Flexbox and Grids
First, I will create a div with the class grid. In order to use the grid layout, I will set the div’s display to grid in my CSS. Put some child elements within this container div with class grid in order to see its default behavior.
.grid {
display: grid
}
After you set display: grid, you notice nothing really changes. We will have to define other CSS properties in order to see the effects of CSS grid.
This grid-template-columns property will actually cause things to change. If you have two child elements of the grid-display div, the first one will take up 40% of the available space and the second will take 50%. If you have more than two, the third, fourth, fifth, etc. will follow this same pattern, wrapping to the next line as necessary.
grid-template-columns: 40% 30% 30%;
You can add as many percentages as you like, as long as they add up to 100%. For each percentage, a new column will be placed onto the each line.
grid-column-gap: 1em;
grid-row-gap: 1em;
The grid-column-gap property adds spacing between each column (on the same line). The grid-row-gap property adds spacing between each row (between 2 lines). The grid-gap property will add the same amount of spacing to both rows and columns.
The recommended unit when using the grid-template-columns property is fractions.
This line, for example, separates the layout into 3 equal-sized columns– 1/3 each.
grid-template-columns: 1fr 1fr 1fr;
This line separates the layout into 1/4, 1/2, then 1/4 of the available width.
grid-template-columns: 1fr 2fr 1fr;
In order to make the syntax more succinct, you can write repeating template column layouts like this:
grid-template-columns: repeat(3, 1fr);
The above line does the same as 1fr 1fr 1fr. The below line repeats 1fr, 2fr, 1fr, 2fr, etc. four times.
grid-template-columns: repeat(3, 1fr, 2fr);
This line sets the height for every grid cell:
grid-auto-rows: 100px;
This line makes the default cell height 100px but expands a cell (and the other cells on its line) if the cell’s content requires more room:
grid-auto-rows: minmax(100px, auto);
The justify-items property allows you to define the location of grid cells within their defined space along the primary axis. It’s very similar to the justify property in Flexbox.
This is the default value of the justify-items property. It makes cells take up their entire horizontal space (in a horizontal grid).
The align-items property allows you to define the location of grid cells within their defined space along the cross axis. It’s very similar to the align property in Flexbox.
This is the default value of the align-items property. It makes cells take up their entire vertical space (in a horizontal grid).
You can set the justify and align properties of each individual grid element in order to only affect that element.
The grid-column and grid-row properties allow you to expand the amount of cell spaces that an individual cell takes up. These properties do this by using a property called lines.
Lines are the spaces between cells.
This line will make Cell 1 expand from row lines 1-3 (vertical expansion).
Component-level state is the state within an individual component. It is only available to that component and only affects that component. We can use hooks such as useState to control component-level state.
But what if you want a piece of state to be available to multiple different components or all of your components? This is what we call application-level state.
Application-level state is the state that is available to the entire application. In order to implement this type of state, we need to implement more complex solutions.
One solution would be to “lift up” the state. This involved moving the piece of state to your App component, the root component which holds all of the other components. While this is a bit simpler to implement than other solutions, the problem with it is that you are giving the App component state that it doesn’t directly need and you will have to pass down the state to each component in a very long-winded way. This is called prop-drilling.
Instead, we can use the Context API as a more dynamic and versatile solution. Here’s an example of how it would be used:
The default path to MySQL on Mac is /usr/local/mysql/bin.
If you type mysql --version, you may get an error saying “command not found.” This is because you don’t have the MySQL command in your path.
To solve this, you can do one of two things:
# This will add MySQL to your current session (will be lost when you close Terminal)
export PATH=${PATH}:/usr/local/mysql/bin
# Permanantly
echo 'export PATH="/usr/local/mysql/bin:$PATH"' >> ~/.bash_profile
Copy and paste whichever command you prefer into Terminal. Close & reopen your Terminal window after you run the command.
Now, if you type mysql --verison, it should show you your version of MySQL.
Log in and use MySQL in the Terminal using this command: mysql -u root -p. It will ask for your password; make sure you use your MySQL password, not your system password
Ctrl + L to clear the prompt
Show users:
SELECT User, Host FROM mysql.user;
Create user: When you create a new database for a new application, you will probably want to have a specific user for that database rather than using the root user
CREATE USER 'someuser'@'localhost' IDENTIFIED BY 'somepassword';
No one likes messy code, but no one likes painstakingly formatting their code as they write it either. The Prettier plugin on VS Code takes care of that for us.
To install it, navigate to the fifth panel on the VS Code sidebar
Type “Prettier” into the search bar and it should be the first option in the list
It’s installed now, but we’re not done. We have to do some set up to get Prettier working in our files.
Navigate to the Settings at the bottom left corner of the screen.
Type “format on save” into the search bar. Change this property to true. This will make it so that whenever we save a file that we’re working on, Prettier will automatically format it for us.
Type “prettier” into the search bar. You will see a list of around 20 properties that dictate the formatting rules Prettier will follow. Change these settings to your preference.
For example, you can change “prettier.singleQuote” to true if you don’t want to deal with some of your code using double quotes and other parts using single quotes.
Save your new settings, close VS Code, and you’re good to go!
To accomplish this, we will be using an npm package called dotenv.
Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env
Install the dotenv package
npm i dotenv
2. Require dotenv in the server file
require('dotenv').config();
3. Create a new file in your project called .env
4. In the .env file, paste all of your API keys
API_KEY=4423b234y329324b32
5. Access the API key with process.env
const api_key = process.env.API_KEY;
6. Create a .gitignore file and add the .env file to it
The code in the .gitignore file:
.env
7. Upload to Github!
It’s recommended to include something that will help others understand what to do with .env variables whether that be using the README, .env_sample, etc.