The Complete Modern React Developer 2022



Introduction

This can be a course for changing into a Full Trendy React Developer in 2022. The one three matters which aren’t coated on this course are Redux, GraphQL and React Native which could possibly be coated in a future course. TypeScript goes to be the primary programming language coated nevertheless for those who already know JavaScript then it’s best to discover it fairly simple to grasp as a result of the syntax is just not that a lot completely different.

We can be constructing an excellent fundamental Twitter clone that has CRUD performance for posting, studying and deleting tweets.

This course offers you the talents and information to develop into a Software program Developer throughout the total stack. On this course you’ll study:



Stipulations

Guarantee that you’ve your improvement surroundings setup and set up all the instruments/libraries listed within the introduction. I work on a Mac so among the instruments I point out can be macOS solely nevertheless it’s best to be capable of discover options and be capable of observe alongside for those who use Home windows or Linux.



MongoDB Setup

You have to to put in the next instruments for working with MongoDB NoSQL databases. MongoDB Compass is a GUI for working with MongoDB databases. And mongosh is a MongoDB shell for working with MongoDB databases utilizing the command line.

MongoDB Compass
mongosh



PostgreSQL Setup

You have to to put in the next instruments for working with PostgreSQL databases. Postgres.app is an app for managing PostgreSQL databases. And Pgcli is a command line interface for Postgres which comes with auto-completion and syntax highlighting. It’s the PostgreSQL equal of mongosh.

My choice is Valentina Studio in the case of utilizing a GUI for working with PostgreSQL databases. It is an awesome device as a result of it will probably even hook up with MongoDB and MySQL databases. There are options although like PgAdminso simply use no matter you’re feeling comfy with.

Postgres.app
Pgcli
Valentina Studio



Organising the backend

On this part you’ll learn to setup a Node backend utilizing each Categorical.js and Nest.js. Each frameworks will hook up with a MongoDB and PostgreSQL database utilizing completely different endpoints. And as a bonus additionally, you will study some DevOps after we put a MongoDB and PostgreSQL database inside a Docker container.

Docker principally provides builders the power to bundle functions inside containers. So primarily you possibly can simply have a database inside a Docker container which any exterior software will be capable of hook up with. With any such setup you do not even want to put in or setup a database in your native machine. You’ll be able to simply have all the pieces operating inside a Docker container and this setup will run precisely the identical on anyones machine.

I believe this an awesome various to having a neighborhood set up and with this data it provides you an alternative choice for interacting with databases. This workflow doesn’t require an enormous setup and you need to use both the GUI or command line to work together together with your database inside the Docker container the identical method you’d if it was native or on-line.



Native Database Setup

Pgcli Commands
mongosh Commands



MongoDB Native

Open your command line device I can be utilizing Hyper and run the command beneath to hook up with your native MongoDB set up.

mongosh
Enter fullscreen mode

Exit fullscreen mode

Firstly run this command which is able to present you which ones database you might be utilizing. It ought to return take a look at which is the default database.

db
Enter fullscreen mode

Exit fullscreen mode

Now run the command beneath which is able to present you which ones databases you at the moment have created.

present dbs;
Enter fullscreen mode

Exit fullscreen mode

Subsequent run the command to create a database known as twitter.

use twitter;
Enter fullscreen mode

Exit fullscreen mode

Lastly create a group utilizing the command beneath and while you use the command present dbs; once more within the command line it’s best to see the database known as twitter which you created.

db.createCollection('contents');
Enter fullscreen mode

Exit fullscreen mode

Lastly we’ll add some beginning knowledge copy and paste the code beneath into your command line. In the event you run this command db.contents.discover().fairly() in your command line after you could have inserted the information then it is possible for you to to see the information within the desk.

db.contents.insertMany([ {tweet: "Hello World!", img: ""}, {tweet: "Content creation and programming are basically full time jobs. I have enough projects and work to keep me busy for years. Working in tech is definitely going to entertain you for a long time which is why so many people want to transition into this field.", img: ""}, {tweet: "JavaScript developers are forever in high demand", img: ""} ])
Enter fullscreen mode

Exit fullscreen mode

In the event you open the MongoDB Compass software in your laptop and hook up with your native set up utilizing the connection string mongodb://localhost:27017 then it’s best to be capable of see all your databases together with the one we simply created within the GUI. So now you might be setup to make use of both the command line or the GUI for interacting together with your databases.



PostgreSQL Native

Earlier than you do something examine that your PostgreSQL database is operating regionally. If it isn’t operating you then would possibly get an error within the command line while you run the command pgcli. On macOS I can be utilizing the Postgres.app so get it operating in your machine after which it ought to present up in your menu bar on the prime of your working system.

Now go to the command line and run the command beneath to hook up with your native PostgreSQL set up.

pgcli
Enter fullscreen mode

Exit fullscreen mode

Operating the command beneath will present you all your PostgreSQL databases.

l
Enter fullscreen mode

Exit fullscreen mode

Copy and paste the SQL question beneath into your pgcli command line window to create a database known as twitter. Now for those who run the command l once more in that very same window it’s best to see all the databases together with the one we simply created.

CREATE DATABASE twitter;
Enter fullscreen mode

Exit fullscreen mode

Subsequent we have to hook up with the database in the identical window so use the command beneath to do this.

c twitter
Enter fullscreen mode

Exit fullscreen mode

Subsequent we’ve to create a desk and add some knowledge which is able to go inside the database twitter. Copy and paste the SQL code beneath into your command line window.

CREATE TABLE contents (

id UUID DEFAULT gen_random_uuid (),

tweet VARCHAR(280) NOT NULL,

img VARCHAR(500) NOT NULL

);

INSERT INTO contents (tweet, img)

VALUES ('Whats up World!', ''), ('Content material creation and programming are principally full time jobs. I've sufficient initiatives and work to maintain me busy for years. Working in tech is unquestionably going to entertain you for a very long time which is why so many individuals need to transition into this discipline.', ''), ('JavaScript builders are perpetually in excessive demand', '');
Enter fullscreen mode

Exit fullscreen mode

In the event you open the Postgres.app software in your laptop it’s best to see all the databases together with the one which we simply created.

https://res.cloudinary.com/d74fh3kw/image/upload/v1650553228/postgresql-app-twitter_ygwp3z.png

And for those who hook up with Valentina Studio or your database GUI of selection it’s best to be capable of see the database you created.



PostgreSQL database connection settings

https://res.cloudinary.com/d74fh3kw/image/upload/v1650553476/valentina-db-twitter-connection_ktkq6v.png



Valentina Studio

https://res.cloudinary.com/d74fh3kw/image/upload/v1650553510/valentina-db-twitter_rss8fv.png



Docker database setup

Begin the Docker software in your laptop and observe the steps beneath for every database. Firstly create a folder in your native machine known as complete-react-developer
after which cd into utilizing the command line.



MongoDB Docker

Double examine that you’re inside the foundation folder for complete-react-developer after which run the instructions beneath to setup the undertaking.

mkdir docker-twitter-mongodb
cd docker-twitter-mongodb
contact docker-compose.yml
Enter fullscreen mode

Exit fullscreen mode

Open that folder in your code editor and add the next code to the docker-compose.yml file.

docker-compose.yml

Watch out with the yaml code formatting if the indentation is just not right it offers you errors.

model: '3.9'
companies:
  mongo_db:
    container_name: db_container
    picture: 'mongo:newest'
    restart: at all times
    ports:
      - '2717:27017'
    volumes:
      - 'mongo_db:/knowledge/db'
volumes:
  mongo_db: {}
Enter fullscreen mode

Exit fullscreen mode

Now run the code beneath to begin the docker container with the MongoDB database.

docker compose up
Enter fullscreen mode

Exit fullscreen mode

Assuming all the pieces went appropriately it’s best to have a MongoDB Database operating inside a Docker Container.

https://res.cloudinary.com/d74fh3kw/image/upload/v1650622543/docker-mongodb_nf7ezr.png



Connecting to the MongoDB Database contained in the Docker Container

It’s now attainable to hook up with the native MongoDB Database and the MongoDB Docker Database concurrently as a result of they’re each configured to run on completely different ports.

The native MongoDB Database is on port 27017 so use the command beneath for connecting to the native mongodb database.

mongosh --port 27017
Enter fullscreen mode

Exit fullscreen mode

The connection string for MongoDB Compass would be the following.

mongodb://localhost:27017
Enter fullscreen mode

Exit fullscreen mode

The MongoDB Docker Database is on port 2717 so use the command beneath for connecting to the Docker MongoDB database.

mongosh --port 2717
Enter fullscreen mode

Exit fullscreen mode

The connection string for MongoDB Compass would be the following.

mongodb://localhost:2717
Enter fullscreen mode

Exit fullscreen mode

So now you could have two MongoDB databases for Twitter one native and one in a Docker Container. Let’s add some knowledge to the database which can be going to persist even for those who delete the container.

Within the command line open a mongosh connection to the MongoDB Database inside the Docker container.

mongosh --port 2717
Enter fullscreen mode

Exit fullscreen mode

Run the instructions beneath. You might be making a database known as twitter with a group known as contents. After which you might be inserting some knowledge into the database.

use twitter;

db.createCollection('contents');

db.contents.insertMany([ {tweet: "Hello World!", img: ""}, {tweet: "Content creation and programming are basically full time jobs. I have enough projects and work to keep me busy for years. Working in tech is definitely going to entertain you for a long time which is why so many people want to transition into this field.", img: ""}, {tweet: "JavaScript developers are forever in high demand", img: ""} ]);
Enter fullscreen mode

Exit fullscreen mode

Now while you run the command db.contents.discover().fairly(); inside the command line it ought to return the information you simply inserted. In the event you go to MongoDB compass and use this connection string mongodb://localhost:2717 it’s best to see the twitter database with the information inside.



PostgreSQL Docker

Examine that you’re inside the foundation folder for complete-react-developer after which run the instructions beneath to setup the undertaking.

mkdir docker-twitter-postgresql
cd docker-twitter-postgresql
contact docker-compose.yml
mkdir sql
cd sql
contact twitter.sql
cd ..
Enter fullscreen mode

Exit fullscreen mode

Open that folder in you code editor and add the next code to the docker-compose.yml and twitter.sql recordsdata.

docker-compose.yml

Watch out with the yaml code formatting if the indentation is just not right it offers you errors.

model: '3.7'
companies:
  postgres:
    picture: postgres:newest
    restart: at all times
    surroundings:
      - POSTGRES_USER=twitter
      - POSTGRES_PASSWORD=twitter
      - POSTGRES_DB=twitter
    ports:
      - '5433:5432'
    volumes:
      - ./postgres-data:/var/lib/postgresql/knowledge
      # copy the sql script to create tables
      - ./sql/twitter.sql:/docker-entrypoint-initdb.d/twitter.sql
Enter fullscreen mode

Exit fullscreen mode

twitter.sql

CREATE TABLE contents (

id UUID DEFAULT gen_random_uuid (),

tweet VARCHAR(280) NOT NULL,

img VARCHAR(500) NOT NULL

);

INSERT INTO contents (tweet, img)

VALUES ('Whats up World!', ''), ('Content material creation and programming are principally full time jobs. I've sufficient initiatives and work to maintain me busy for years. Working in tech is unquestionably going to entertain you for a very long time which is why so many individuals need to transition into this discipline.', ''), ('JavaScript builders are perpetually in excessive demand', '');
Enter fullscreen mode

Exit fullscreen mode

Now run the code beneath to begin the Docker Container with the PostgreSQL database.

docker compose up
Enter fullscreen mode

Exit fullscreen mode

If you see the log that claims database system is able to settle for connections you’ll know that it is working. This will also be verified within the Docker Desktop Utility for those who examine it it’s best to see the container operating.

https://res.cloudinary.com/d74fh3kw/image/upload/v1650557620/docker-postgresql_z3nl5i.png

What we’ve simply carried out is setup a PostgreSQL database which is able to reside inside a Docker container. This database is even going to have some prebuilt knowledge from the SQL script that we created.



Connecting to the PostgreSQL Database contained in the Docker Container

The docker-compose.yml file inside the docker-twitter-postgresql folder has a port mapping of 5433:5432. 5433 is the native port and 5432 is the docker port which can be the default for Postgres. I did it this fashion in order that we are able to use the Postgres app on port 5432 regionally and run the Docker database on port 5433 concurrently.

So right here is the place the magic occurs! Use the connection credentials within the picture beneath and it’s best to be capable of hook up with the PostgreSQL database inside the docker container!

The password is twitter by the way in which and yow will discover the credentials inside the docker-compose.yml file.

https://res.cloudinary.com/d74fh3kw/image/upload/v1650558031/docker-postgresql-db-connection_xajz8z.png

So now we’ve a neighborhood PostgreSQL database known as twitter on port 5432. And a Docker PostgreSQL database known as twitter on port 5433. Valentina Studio can hook up with each of them concurrently and you’ll run all your SQL queries. Whats extra the PostgreSQL database inside the Docker container can persist its knowledge. In the event you had been to delete the operating Docker container after which run the command docker compose up once more all the pieces will stay the identical!

Use the command docker compose down to cease the Docker container from operating if that you must.

Congratulations you simply learnt the fundamentals of MongoDB, PostgreSQL and Docker!



Node backend setup

This can be cut up into two sections. One for making a backend utilizing Categorical.js and TypeScript. And one other for making a backend utilizing Nest.js and TypeScript so you possibly can see the distinction between the 2 and study alternative routes for growing a backend in Node.

So there can be 4 Node backends to mess around with:

  • backend-express-mongodb
  • backend-express-postgresql
  • backend-nest-mongodb
  • backend-nest-postgresql

A REST API testing device can be wanted with the intention to take a look at the varied routes and endpoints. These are my prime 3 preferences be happy to make use of one thing else if you wish to.

Postman
Thunder Client
Insomnia

You needn’t create all of those backends as a result of after we create the React frontend it can solely require one backend however that is nonetheless good information value studying. And clearly you may simply have one backend that connects to each MongoDB and PostgreSQL it is simply simpler to clarify in these examples.



Categorical App



Backend Categorical MongoDB

Make sure that you’re inside the folder complete-react-developer.

Run the instructions beneath to scaffold your undertaking.

mkdir backend-express-mongodb
cd backend-express-mongodb
tsc --init
npm init -y
npm i specific @sorts/specific @sorts/node ts-node cors @sorts/cors mongoose @sorts/mongoose typescript rimraf copy-files dotenv nodemon
contact .env
mkdir src
cd src
contact app.ts
mkdir controllers fashions routes
contact controllers/Admin.ts
contact fashions/Twitter.ts
contact routes/Admin.ts
cd ..
Enter fullscreen mode

Exit fullscreen mode

Open the undertaking in your code editor and go to the tsconfig.json file inside the foundation folder and allow these properties.

"rootDir": "./src" /* Specify the root folder inside your supply recordsdata. */,
"moduleResolution": "node" /* Specify how TypeScript appears to be like up a file from a given module specifier. */,
"outDir": "./dist/src" /* Specify an output folder for all emitted recordsdata. */,
Enter fullscreen mode

Exit fullscreen mode

Within the subsequent step open the bundle.json file and add these run scripts.

"scripts": {

"begin": "node dist/src/app.js",

"dev": "nodemon src/app.ts",

"clear": "rimraf dist/",

"construct": "npm run clear && tsc && npm run copy-files",

"copy-files": "copyfiles -u 1 src/**/*.html src/**/*.css src/**/*.json dist/src"

},
Enter fullscreen mode

Exit fullscreen mode



Run Scripts

begin
The beginning script runs the appliance utilizing Node with out auto reload when there are updates to the recordsdata.

dev
The dev script makes use of nodemon to routinely auto reload and replace the recordsdata when there are modifications.

clear
The clear script deletes the dist folder.

construct
The construct script deletes the dist folder after which routinely copies all the recordsdata and places them again into the dist folder.

copy-files
The copy recordsdata script is used for copying the recordsdata from one listing to a special one.



Including the code

Lastly add the code beneath to their corresponding recordsdata.

controllers/Admin.ts

import { Response, Request } from 'specific';

import mongoose from 'mongoose';

import Twitter from '../fashions/Twitter';

export const getTweets = (req: Request, res: Response): void => {
    Twitter.discover((err, knowledge) => {
        console.log(knowledge);

        res.json(knowledge);

        if (err) {
            console.log(err);
        }
    });
};

export const getTweet = async (req: Request, res: Response): Promise<any> => {
    const tweetId = req.params.tweetId;

    console.log('Tweet ID', tweetId);

    // This line of code fixes the CastError: Solid to ObjectId failed for worth "favicon.ico" (sort string) at path "_id" for mannequin "contents"

    if (!mongoose.Varieties.ObjectId.isValid(tweetId)) return false;

    await Twitter.findById(tweetId).exec();

    Twitter.findById(tweetId, (err: any, tweet: any) => {
        console.log(tweet);

        res.json(tweet);

        if (err) {
            console.log(err);
        }
    });
};

export const postTweet = (req: Request, res: Response) => {
    const { tweet, img } = req.physique;

    const twitter = new Twitter({ tweet: tweet, img: img });

    twitter.save();

    console.log('Tweet Created');

    res.standing(201).json({ msg: 'Tweet Created' });
};

export const updateTweet = (req: Request, res: Response) => {
    const tweetId = req.params.tweetId;

    const { tweet, img } = req.physique;

    Twitter.findByIdAndUpdate(tweetId, { tweet: tweet, img: img }).then(() => {
        console.log(`Tweet ${tweetId} Up to date`);

        res.json({ msg: `Tweet ${tweetId} Up to date` });
    });
};

export const deleteTweet = (req: Request, res: Response) => {
    const tweetId = req.physique.tweetId;

    Twitter.findByIdAndRemove(tweetId, () => {
        res.json({ msg: `Tweet ${tweetId} Deleted` });
    });
};
Enter fullscreen mode

Exit fullscreen mode

fashions/Twitter.ts

import { Schema, mannequin } from 'mongoose';

interface Twitter {
    tweet: string;

    img: string;
}

const schema = new Schema<Twitter>({
    tweet: { sort: String, required: true },

    img: { sort: String, required: false },
});

const TwitterModel = mannequin<Twitter>('contents', schema);

export default TwitterModel;
Enter fullscreen mode

Exit fullscreen mode

routes/Admin.ts

import specific from 'specific';

import { getTweets, getTweet, postTweet, updateTweet, deleteTweet } from '../controllers/Admin';

const router = specific.Router();

router.get('/', getTweets);

router.get('/:tweetId', getTweet);

router.put up('/delete', deleteTweet);

router.put up('/tweet', postTweet);

router.put up('/:tweetId', updateTweet);

export default router;
Enter fullscreen mode

Exit fullscreen mode

app.ts

import dotenv from 'dotenv';

dotenv.config();

console.log(course of.env.DB_HOST);

import specific from 'specific';

import cors from 'cors';

import mongoose from 'mongoose';

import adminRoute from './routes/Admin';

const app = specific();

app.use(cors());

app.use(specific.urlencoded({ prolonged: false }));

app.use(specific.json());

app.use('/', adminRoute);

const port = course of.env.PORT || 8080;

mongoose

    // Use DB_HOST_DOCKER to hook up with the MongoDB Database within the Docker Container

    .join(`${course of.env.DB_HOST_LOCAL}`)

    .then(() => {
        app.hear(port, () => console.log(`Server and database operating on port ${port}, http://localhost:${port}`));
    })

    .catch((err: any) => {
        console.log(err);
    });
Enter fullscreen mode

Exit fullscreen mode

.env

DB_HOST_LOCAL="mongodb://127.0.0.1:27017/twitter"

DB_HOST_DOCKER="mongodb://127.0.0.1:2717/twitter"
Enter fullscreen mode

Exit fullscreen mode

The applying is setup to hook up with a neighborhood MongoDB database however you possibly can change this within the app.ts file and yow will discover the database connection strings within the .env file.

Use the command beneath to begin the server.

npm run dev
Enter fullscreen mode

Exit fullscreen mode



Testing the API

I can be utilizing Postman however you need to use no matter API Testing device you need. If you wish to see it totally working the very first thing you’ll have to do is add some knowledge to the database if in case you have not carried out so already. Use the Create tweet route for this and see the examples within the screenshots beneath.



GET all tweets

https://res.cloudinary.com/d74fh3kw/image/upload/v1650806989/postman-get-tweets_osgha3.png



GET tweet by ID

https://res.cloudinary.com/d74fh3kw/image/upload/v1650807143/postman-get-tweet_lc03qt.png



CREATE tweet

https://res.cloudinary.com/d74fh3kw/image/upload/v1650807209/postman-post-tweet_p7fycd.png



UPDATE tweet by ID

https://res.cloudinary.com/d74fh3kw/image/upload/v1650807250/postman-update-tweet_vvookc.png



DELETE tweet

https://res.cloudinary.com/d74fh3kw/image/upload/v1650807306/postman-delete-tweet_mp4bs1.png



Backend Categorical PostgreSQL

We can be utilizing https://typeorm.io/to create an Categorical.js software that connects to a PostgreSQL database.

Try to be inside the folder complete-react-developer.

Run the instructions beneath to scaffold your undertaking.

mkdir backend-express-postgresql
cd backend-express-postgresql
tsc --init
npm init -y
npm i specific @sorts/specific @sorts/node ts-node cors @sorts/cors typescript rimraf copy-files dotenv nodemon pg reflect-metadata typeorm
mkdir src
cd src
contact app.ts app-data-source.ts
mkdir entity
cd entity
contact Tweet.ts
cd ../..
Enter fullscreen mode

Exit fullscreen mode

Open the undertaking in your code editor discover the tsconfig.json file and exchange all the code inside it with the code beneath.

{
    "compilerOptions": {
        "lib": ["es5", "es6", "dom"],

        "goal": "es5",

        "module": "commonjs",

        "moduleResolution": "node",

        "emitDecoratorMetadata": true,

        "experimentalDecorators": true,

        "rootDir": "./src",

        "outDir": "./dist/src"
    }
}
Enter fullscreen mode

Exit fullscreen mode

Within the subsequent step open the bundle.json file and add these run scripts.

"scripts": {

"begin": "node dist/src/app.js",

"dev": "nodemon src/app.ts",

"clear": "rimraf dist/",

"construct": "npm run clear && tsc && npm run copy-files",

"copy-files": "copyfiles -u 1 src/**/*.html src/**/*.css src/**/*.json dist/src"

},
Enter fullscreen mode

Exit fullscreen mode

Add the code beneath to the corresponding recordsdata.

entity/Tweet.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Tweet {
    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column()
    tweet: string;

    @Column()
    img: string;
}
Enter fullscreen mode

Exit fullscreen mode

app-data-source.ts

import { DataSource } from 'typeorm';

export const myDataSource = new DataSource({
    sort: 'postgres',

    host: 'localhost',

    port: 5432,

    username: 'postgres',

    password: '',

    database: 'twitter',

    entities: ['dist/src/entity/*.js'],

    logging: true,

    synchronize: true,
});
Enter fullscreen mode

Exit fullscreen mode

app.ts

import * as specific from 'specific';

import { Request, Response } from 'specific';

import { Tweet } from './entity/Tweet';

import { myDataSource } from './app-data-source';

// set up database connection

myDataSource

    .initialize()

    .then(() => {
        console.log('Information Supply has been initialized!');
    })

    .catch((err) => {
        console.error('Error throughout Information Supply initialization:', err);
    });

// create and setup specific app

const app = specific();

app.use(specific.json());

app.use(specific.urlencoded({ prolonged: false }));

// register CRUD routes

// CREATE

// READ

// UPDATE

// DELETE

// READ: All tweets

app.get('/tweets', async perform (req: Request, res: Response) {
    const tweets = await myDataSource.getRepository(Tweet).discover();

    res.json(tweets);
});

// READ: Tweet by ID

app.get('/tweets/:id', async perform (req: Request, res: Response) {
    const outcomes = await myDataSource.getRepository(Tweet).findOneBy({
        id: req.params.id,
    });

    return res.ship(outcomes);
});

// CREATE: New tweet

app.put up('/tweets', async perform (req: Request, res: Response) {
    const tweet = await myDataSource.getRepository(Tweet).create(req.physique);

    const outcomes = await myDataSource.getRepository(Tweet).save(tweet);

    return res.ship(outcomes);
});

// UPDATE: Tweet by ID

app.put('/tweets/:id', async perform (req: Request, res: Response) {
    const tweet = await myDataSource.getRepository(Tweet).findOneBy({
        id: req.physique.id,
    });

    myDataSource.getRepository(Tweet).merge(tweet, req.physique);

    const outcomes = await myDataSource.getRepository(Tweet).save(tweet);

    return res.ship(outcomes);
});

// DELETE: Tweet by ID

app.delete('/tweets/:id', async perform (req: Request, res: Response) {
    const outcomes = await myDataSource.getRepository(Tweet).delete(req.physique.id);

    return res.ship(outcomes);
});

const port = course of.env.PORT || 8080;

// begin specific server

app.hear(port, () => console.log(`Server and database operating on port ${port}, http://localhost:${port}`));
Enter fullscreen mode

Exit fullscreen mode

The applying is setup to hook up with a neighborhood PostgreSQL database however you possibly can change this within the app-data-source.ts file. The Docker connection settings may be discovered within the Docker part for those who want them. Do not forget that that you must have your PostgreSQL database setup and operating earlier than you possibly can hook up with it.

Use the instructions beneath to run the app.

Warning: You would possibly get the error EntityMetadataNotFoundError: No metadata for "Tweet" was discovered. for those who attempt to use the command npm run dev which makes use of nodemon to begin the appliance. I believe it has one thing to do with static and dynamic knowledge and the truth that nodemon is auto reloading. So it is safer to make use of the instructions beneath and simply do a clear construct utilizing the node server which will not replace till you manually restart it.

npm run construct
npm run begin
Enter fullscreen mode

Exit fullscreen mode

Try to be acquainted with utilizing a REST API device now nevertheless the routes and CRUD requests are barely completely different on this instance. See the examples beneath and do not forget to make use of the CREATE tweet route so as to add some knowledge into the database with the intention to see some knowledge.



GET all tweets

Request: GET
Route: http://localhost:8080/tweets



GET tweet by ID

Request: GET
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1



CREATE tweet

Request: POST
Route: http://localhost:8080/tweets
Physique uncooked: {“tweet”: ‘Whats up World’, img: “”}



UPDATE tweet by ID

Request: PUT
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1
Physique uncooked: {“tweet”: ‘Whats up Moon’, img: “”}



DELETE tweet by ID

Request: DELETE
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1
Physique: x-www-form-urlencoded
KEY: id
VALUE: Your id



Nest App



Backend Nest MongoDB

It is time to create the Nest backend that may hook up with MongoDB. Get inside the folder complete-react-developer and run the command beneath. Choose your most well-liked bundle supervisor I’m going to decide on npm. In the event you select a special choice keep in mind to run the proper instructions for it in a while.

nest new backend-nest-mongodb
Enter fullscreen mode

Exit fullscreen mode

Open the undertaking in your code editor and prepare to generate some controller and repair recordsdata. We will even set up mongoose first cd into the backend-nest-mongodb folder within the command line and run the instructions beneath.

cd backend-nest-mongodb
npm set up --save @nestjs/mongoose mongoose
nest g controller twitter
nest g service twitter
Enter fullscreen mode

Exit fullscreen mode

Earlier than we create the opposite undertaking recordsdata lets do some file cleanup. Delete the next recordsdata:

app.service.ts
app.controller.ts
app.controller.spec.ts

Now it is time to create the remainder of the recordsdata for this undertaking. Get inside the foundation folder for backend-nest-mongodb and run the instructions beneath.

contact src/twitter/twitter.module.ts
mkdir src/twitter/{dto,schemas}
contact src/twitter/dto/create-twitter.dto.ts
contact src/twitter/schemas/twitter.schema.ts
Enter fullscreen mode

Exit fullscreen mode

Now we have created all the recordsdata which might be going to be required for this undertaking let’s add the code now. Add or exchange the code within the current recordsdata with the code beneath:

app.module.ts

import { Module } from '@nestjs/frequent';

import { MongooseModule } from '@nestjs/mongoose';

import { TwitterController } from './twitter/twitter.controller';

import { TwitterService } from './twitter/twitter.service';

import { TwitterModule } from './twitter/twitter.module';

@Module({
    imports: [
        TwitterModule,

        // Local MongoDb database

        // Change the port to 127.0.0.1:2717 to connect to Docker

        MongooseModule.forRoot('mongodb://127.0.0.1:27017/twitter'),
    ],

    controllers: [TwitterController],

    suppliers: [TwitterService],
})
export class AppModule {}
Enter fullscreen mode

Exit fullscreen mode

twitter.service.ts

import { Mannequin } from 'mongoose';

import { Injectable } from '@nestjs/frequent';

import { InjectModel } from '@nestjs/mongoose';

import { Twitter, TwitterDocument } from './schemas/twitter.schema';

import { CreateTwitterDto } from './dto/create-twitter.dto';

@Injectable()
export class TwitterService {
    constructor(@InjectModel(Twitter.title) non-public twitterModel: Mannequin<TwitterDocument>) {}

    async create(createTwitterDto: CreateTwitterDto): Promise<Twitter> {
        const createdTwitter = new this.twitterModel(createTwitterDto);

        return createdTwitter.save();
    }

    async findAll(): Promise<Twitter[]> {
        return this.twitterModel.discover().exec();
    }

    async findOne(id: string): Promise<Twitter> {
        return this.twitterModel.findOne({ _id: id });
    }

    async replace(id: string, twitter: Twitter): Promise<Twitter> {
        return this.twitterModel.findByIdAndUpdate(id, twitter, { new: true });
    }

    async delete(id: string): Promise<Twitter> {
        return this.twitterModel.findByIdAndRemove({ _id: id });
    }
}
Enter fullscreen mode

Exit fullscreen mode

twitter.module.ts

import { Module } from '@nestjs/frequent';

import { MongooseModule } from '@nestjs/mongoose';

import { Twitter, TwitterSchema } from './schemas/twitter.schema';

@Module({
    imports: [MongooseModule.forFeature([{ name: Twitter.name, schema: TwitterSchema }])],

    exports: [MongooseModule],
})
export class TwitterModule {}
Enter fullscreen mode

Exit fullscreen mode

twitter.controller.ts

import { Controller, Get, Publish, Physique, Param, Put, Delete } from '@nestjs/frequent';

import { CreateTwitterDto, TwitterDto } from './dto/create-twitter.dto';

import { TwitterService } from './twitter.service';

@Controller('tweets')
export class TwitterController {
    constructor(non-public twitterService: TwitterService) {}

    @Publish()
    async create(@Physique() createTwitterDto: CreateTwitterDto) {
        this.twitterService.create(createTwitterDto);
    }

    @Get()
    async findAll(): Promise<TwitterDto[]> {
        return this.twitterService.findAll();
    }

    @Get(':id')
    async findOne(@Param('id') id): Promise<TwitterDto> {
        return this.twitterService.findOne(id);
    }

    @Put(':id')
    replace(
        @Physique() updateTwitterDto: CreateTwitterDto,

        @Param('id') id
    ): Promise<TwitterDto> {
        return this.twitterService.replace(id, updateTwitterDto);
    }

    @Delete(':id')
    delete(@Param('id') id): Promise<TwitterDto> {
        return this.twitterService.delete(id);
    }
}
Enter fullscreen mode

Exit fullscreen mode

schemas/twitter.schema.ts

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

import { Doc } from 'mongoose';

export sort TwitterDocument = Twitter & Doc;

@Schema()
export class Twitter {
    @Prop()
    tweet: string;

    @Prop()
    img: string;
}

export const TwitterSchema = SchemaFactory.createForClass(Twitter);
Enter fullscreen mode

Exit fullscreen mode

dto/create-twitter.dto.ts

export class CreateTwitterDto {
    id?: string;

    tweet: string;

    img: string;
}

export class TwitterDto {
    id?: string;

    tweet: string;

    img: string;
}
Enter fullscreen mode

Exit fullscreen mode

Every part needs to be setup now the backend is configured to hook up with a neighborhood MongoDB database. You’ll be able to change this to Docker by modifying the connection string inside the app.module.ts file.

Run the command beneath to begin the appliance in watch mode.

npm run begin:dev
Enter fullscreen mode

Exit fullscreen mode

One vital factor to say is that by default NestJS functions run on port 3000 which is similar default port that our React software goes to make use of. So for consistency you would possibly need to change it to 8080 or a special port. You are able to do this within the predominant.ts file. Additionally you will have to allow CORS in any other case you’re going to get that annoying CORS error while you attempt to join the backend to the frontend.

predominant.ts

import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';

async perform bootstrap() {
    const app = await NestFactory.create(AppModule);

    app.enableCors();

    await app.hear(8080);
}

bootstrap();
Enter fullscreen mode

Exit fullscreen mode

The routes needs to be the identical as earlier than here’s a refresher you can take a look at in Postman or no matter REST API device you might be utilizing:



GET all tweets

Request: GET
Route: http://localhost:8080/tweets



GET tweet by ID

Request: GET
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1



CREATE tweet

Request: POST
Route: http://localhost:8080/tweets
Physique uncooked: {“tweet”: ‘Whats up World’, img: “”}



UPDATE tweet by ID

Request: PUT
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1
Physique uncooked: {“tweet”: ‘Whats up Moon’, img: “”}



DELETE tweet by ID

Request: DELETE
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1



Backend Nest PostgreSQL

Lastly we are actually going to create the Nest backend that may hook up with PostgreSQL. We are going to lastly transfer onto the React frontend after this stage. Ensure that you might be inside the folder complete-react-developer and run the command beneath. Like within the earlier chapter choose your most well-liked bundle supervisor I’m going to decide on npm. In the event you select a special choice keep in mind to run the proper instructions for it in a while.

nest new backend-nest-postgresql
Enter fullscreen mode

Exit fullscreen mode

Open the undertaking in your code editor and prepare to generate some controller and repair recordsdata. We will even set up PostgreSQL and TypeORM in order that we are able to hook up with PostgreSQL databases. Firstly cd into the backend-nest-postgresql folder within the command line and run the instructions beneath.

cd backend-nest-postgresql
npm set up --save pg @nestjs/typeorm typeorm
nest g controller twitter
nest g service twitter
Enter fullscreen mode

Exit fullscreen mode

Earlier than we create the opposite undertaking recordsdata lets do some file cleanup. Delete the next recordsdata:

app.service.ts
app.controller.ts
app.controller.spec.ts

Now it is time to create the remainder of the recordsdata for this undertaking. If you find yourself inside the foundation folder for backend-nest-postgresql run the instructions beneath.

contact src/twitter/{twitter.module.ts,twitter.entity.ts}
mkdir src/twitter/dto
contact src/twitter/dto/twitter.dto.ts
Enter fullscreen mode

Exit fullscreen mode

Now we have created all the recordsdata which might be going to be required for this undertaking let’s add the code now. Add or exchange the code within the current recordsdata with the code beneath:

app.module.ts

import { Module } from '@nestjs/frequent';

import { TypeOrmModule } from '@nestjs/typeorm';

import { TwitterController } from './twitter/twitter.controller';

import { TwitterService } from './twitter/twitter.service';

import { TwitterModule } from './twitter/twitter.module';

import { Connection } from 'typeorm';

@Module({
    imports: [
        TypeOrmModule.forRoot({
            type: 'postgres',

            host: 'localhost',

            port: 5432,

            username: 'postgres',

            password: '',

            database: 'twitter',

            entities: ['dist/**/*.entity{.ts,.js}'],

            synchronize: false,
        }),

        TwitterModule,
    ],

    controllers: [TwitterController],

    suppliers: [TwitterService],
})
export class AppModule {
    constructor(non-public connection: Connection) {}
}
Enter fullscreen mode

Exit fullscreen mode

twitter.service.ts

import { Injectable, NotFoundException } from '@nestjs/frequent';

import { InjectRepository } from '@nestjs/typeorm';

import { DeleteResult, InsertResult, Repository } from 'typeorm';

import { Twitter } from './twitter.entity';

@Injectable()
export class TwitterService {
    constructor(
        @InjectRepository(Twitter)
        non-public twitterRepository: Repository<Twitter>
    ) {}

    async addTwitter(twitter: Twitter): Promise<InsertResult> {
        return this.twitterRepository.insert(twitter);
    }

    async findAll(): Promise<Twitter[]> {
        return this.twitterRepository.discover();
    }

    async findOne(id: string): Promise<Twitter> {
        return this.twitterRepository.findOne(id);
    }

    async replace(id: string, twitter: Twitter): Promise<Twitter> {
        const twitterUpdate = await this.findOne(id);

        if (twitterUpdate === undefined) {
            throw new NotFoundException();
        }

        await this.twitterRepository.replace(id, twitter);

        return this.twitterRepository.findOne(id);
    }

    async delete(id: string): Promise<DeleteResult> {
        const twitterUpdate = await this.findOne(id);

        if (twitterUpdate === undefined) {
            throw new NotFoundException();
        }

        return this.twitterRepository.delete(id);
    }
}
Enter fullscreen mode

Exit fullscreen mode

twitter.module.ts

import { Module } from '@nestjs/frequent';

import { TypeOrmModule } from '@nestjs/typeorm';

import { TwitterController } from './twitter.controller';

import { TwitterService } from './twitter.service';

import { Twitter } from './twitter.entity';

@Module({
    imports: [TypeOrmModule.forFeature([Twitter])],

    controllers: [TwitterController],

    suppliers: [TwitterService],

    exports: [TypeOrmModule],
})
export class TwitterModule {}
Enter fullscreen mode

Exit fullscreen mode

twitter.entity.ts

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Twitter {
    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column()
    tweet: string;

    @Column()
    img: string;
}
Enter fullscreen mode

Exit fullscreen mode

twitter.controller.ts

import { Controller, Get, Publish, Patch, Delete, Param, Physique } from '@nestjs/frequent';

import { TwitterService } from './twitter.service';

import { TwitterDto } from './dto/twitter.dto';

import { Twitter } from './twitter.entity';

@Controller('tweets')
export class TwitterController {
    constructor(non-public twitterService: TwitterService) {}

    @Publish()
    create(@Physique() twitter: Twitter) {
        return this.twitterService.addTwitter(twitter);
    }

    @Get()
    findAll(): Promise<TwitterDto[]> {
        return this.twitterService.findAll();
    }

    @Get(':id')
    getOneTwitter(@Param('id') id: string): Promise<Twitter> {
        return this.twitterService.findOne(id);
    }

    @Patch(':id')
    updateTwitter(
        @Param('id') id: string,

        @Physique() twitter: Twitter
    ): Promise<Twitter> {
        return this.twitterService.replace(id, twitter);
    }

    @Delete(':id')
    deleteTwitter(@Param('id') id: string) {
        return this.twitterService.delete(id);
    }
}
Enter fullscreen mode

Exit fullscreen mode

dto/twitter.dto.ts

export class TwitterDto {
    tweet: string;

    img: string;
}
Enter fullscreen mode

Exit fullscreen mode

Every part needs to be setup now the backend is configured to hook up with a neighborhood PostgreSQL database. You’ll be able to change this to Docker by modifying the connection particulars inside the app.module.ts file.

There’s one factor of notice although this software is utilizing a database desk known as twitter. Take a look at the instance SQL that you may use for producing some fast take a look at knowledge. In the event you get an error its most likely as a result of its anticipating to discover a desk known as twitter.

CREATE TABLE twitter (



id UUID DEFAULT gen_random_uuid (),



tweet VARCHAR(280) NOT NULL,



img VARCHAR(500) NOT NULL



);



INSERT INTO twitter (tweet, img)



VALUES ('Whats up World!', ''), ('Content material creation and programming are principally full time jobs. I've sufficient initiatives and work to maintain me busy for years. Working in tech is unquestionably going to entertain you for a very long time which is why so many individuals need to transition into this discipline.', ''), ('JavaScript builders are perpetually in excessive demand', '');
Enter fullscreen mode

Exit fullscreen mode

Run the command beneath to begin the appliance in watch mode. Like earlier than the routes are fairly comparable however there are some variations. Additionally do not forget to vary the port to 8080 within the predominant.ts file. Like earlier you will have to allow CORS in any other case you’re going to get that annoying CORS error while you attempt to join the backend to the frontend.

predominant.ts

import { NestFactory } from '@nestjs/core';

import { AppModule } from './app.module';

async perform bootstrap() {
    const app = await NestFactory.create(AppModule);

    app.enableCors();

    await app.hear(8080);
}

bootstrap();
Enter fullscreen mode

Exit fullscreen mode

npm run begin:dev
Enter fullscreen mode

Exit fullscreen mode

You’ll be able to take a look at in Postman or no matter REST API device you might be utilizing:



GET all tweets

Request: GET
Route: http://localhost:8080/tweets



GET tweet by ID

Request: GET
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1



CREATE tweet

Request: POST
Route: http://localhost:8080/tweets
Physique uncooked: {“tweet”: ‘Whats up World’, img: “”}



UPDATE tweet by ID

Request: PATCH
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1
Physique uncooked: {“tweet”: ‘Whats up Moon’, img: “”}



DELETE tweet by ID

Request: DELETE
Route: http://localhost:8080/tweets/d5d29839-788f-4d23-99ee-82b49ff1bbf1
Physique: x-www-form-urlencoded
KEY: id
VALUE: Your id



Organising the frontend

In the end we attain the frontend part! It wont be anyplace close to so long as the backend part we simply accomplished as a result of there’ll solely be ONE React frontend!



Constructing the Twitter Clone App

The applying goes to be a quite simple Twitter Clone. You’ll be able to create, learn and delete tweets. There isn’t any choice to replace/edit tweets which is strictly how it’s proper now anyway πŸ˜‚ Nonetheless the endpoint for updating already exists within the backend so you may implement it for those who wished to. BTW this isn’t a Twitter Clone course so do not anticipate it to be pixel excellent and 100% correct 😁

The codebase is sort of giant so as an alternative of copy and pasting code a dozen occasions and going by way of a protracted undertaking setup I created the appliance and put it on GitHub. So all that you must do is clone/obtain the codebase and run the set up scripts.

https://github.com/andrewbaisden/complete-react-developer

Subsequent open the undertaking in your code editor to see the codebase and use the instructions beneath inside their respective root folders. The setup directions are additionally within the README file.



Setup

Begin the Docker Desktop Utility in your laptop

cd into the foundation folder for backend-nest-mongodb and frontend after which run the instructions beneath to put in the dependencies. You’ll most likely have to power the set up when making an attempt to put in the dependencies for the frontend React software on this case in any other case it might provide you with an error.

# Run this command inside the backend-nest-mongodb folder
npm set up

# Run this command inside the frontend folder
npm set up --force
Enter fullscreen mode

Exit fullscreen mode

  1. cd into the foundation folder for docker-twitter-mongodb and run the command beneath to begin the MongoDB database inside a Docker Container.
docker compose up
Enter fullscreen mode

Exit fullscreen mode

cd into the foundation folder for backend-nest-mongodb and run the command beneath to begin the backend NestJS server.

npm run begin:dev
Enter fullscreen mode

Exit fullscreen mode

cd into the foundation folder for frontend and run the command beneath to begin the frontend React server.

npm run begin
Enter fullscreen mode

Exit fullscreen mode

Use the routes from the Backend Nest MongoDB part if you wish to take a look at them out in your REST API device.



The Twitter Clone App

You need to see your database operating inside a Docker Container and your Twitter Clone React software open within the browser.

Run these instructions inside the foundation folder for frontend which is the place React is. The command beneath begins Storybook.

# Begins Storybook
npm run storybook
Enter fullscreen mode

Exit fullscreen mode

You need to see a Storybook element library open within the browser with a element for composing tweets. You’ll be able to mess around and alter the names within the management to see the way it appears to be like within the demo. The command beneath runs the unit and integration checks.

# Runs the React testing library unit and integration checks
npm run take a look at
Enter fullscreen mode

Exit fullscreen mode

You would possibly have to press a or Enter to set off a brand new take a look at run. The entire checks needs to be passing in your console. The command beneath begins Cypress.

# Runs the Cypress Finish-To-Finish checks
npx cypress open
Enter fullscreen mode

Exit fullscreen mode

A brand new Cypress window ought to open. Run the mixing take a look at and prepare to be amazed because it routinely posts 3 tweets for you! Reload the online web page together with your React software and you will note the brand new tweets there too!



The Context API

This software makes use of the Context API for world state. If you wish to get the appliance to hook up with your MongoDB, PostgreSQL or Docker databases then that you must change the API routes and port numbers http://localhost:8080/tweets. The identical applies to the strategies do not forget that a few of them use POST, PUT, PATCH, DELETE and so on… It depends upon the backend you might be utilizing.

src/contexts/TwitterContext.tsx

import { useEffect, useState, createContext, useContext } from 'react';

interface ContextProps {
    knowledge: any;

    loading: boolean;

    handleToggleComposetweet: any;

    toggleComposeTweet: boolean;

    tweet: string;

    setTweet: any;

    postTweet: any;

    deleteTweet: any;
}

const TwitterContext = createContext({} as ContextProps);

export const useTwitter = () => useContext(TwitterContext);

const TwitterContextProvider = (props: any): any => {
    useEffect(() => {
        const getTweets = () => {
            const API = 'http://localhost:8080/tweets';

            fetch(API)
                .then((response) => {
                    console.log(response);

                    return response.json();
                })

                .then((knowledge) => {
                    console.log(knowledge);

                    setLoading(false);

                    setData(knowledge);
                })

                .catch((err) => {
                    console.log(err);
                });
        };

        getTweets();
    }, []);

    const [data, setData] = useState([]);

    const [loading, setLoading] = useState(true);

    const [toggleComposeTweet, setToggleComposeTweet] = useState(false);

    const [tweet, setTweet] = useState('');

    const handleToggleComposetweet = () => {
        toggleComposeTweet === true ? setToggleComposeTweet(false) : setToggleComposeTweet(true);
    };

    const postTweet = () => {
        if (tweet === '') {
            let myHeaders = new Headers();

            myHeaders.append('Content material-Sort', 'software/json');

            let uncooked = JSON.stringify({
                tweet: 'Congratulations that is what occurs while you put up an empty tweet πŸ€ͺ Create some validation πŸ™ƒ',

                img: '',
            });

            fetch('http://localhost:8080/tweets', { technique: 'POST', headers: myHeaders, physique: uncooked, redirect: 'observe' })
                .then((response) => response.textual content())

                .then((consequence) => console.log(consequence))

                .catch((error) => console.log('error', error));
        } else {
            let myHeaders = new Headers();

            myHeaders.append('Content material-Sort', 'software/json');

            let uncooked = JSON.stringify({
                tweet: tweet,

                img: '',
            });

            fetch('http://localhost:8080/tweets', { technique: 'POST', headers: myHeaders, physique: uncooked, redirect: 'observe' })
                .then((response) => response.textual content())

                .then((consequence) => console.log(consequence))

                .catch((error) => console.log('error', error));
        }
    };

    const deleteTweet = (tweetId: string) => {
        console.log('Deleted', tweetId);

        let urlencoded = new URLSearchParams();

        fetch(`http://localhost:8080/tweets/${tweetId}`, {
            technique: 'DELETE',

            physique: urlencoded,

            redirect: 'observe',
        })
            .then((response) => response.textual content())

            .then((consequence) => console.log(consequence))

            .catch((error) => console.log('error', error));

        window.location.reload();
    };

    const worth = {
        knowledge,

        loading,

        toggleComposeTweet,

        handleToggleComposetweet,

        postTweet,

        tweet,

        setTweet,

        deleteTweet,
    };

    return <TwitterContext.Supplier worth={worth}>{props.youngsters}</TwitterContext.Supplier>;
};

export default TwitterContextProvider;
Enter fullscreen mode

Exit fullscreen mode



Testing with React Testing Library and Jest

There are two take a look at recordsdata one for App.take a look at.tsx and one for TwitterMenu.take a look at.tsx.

I’ll present the instance for App.take a look at.tsx. These checks simply take a look at to see if the required textual content is displaying on the web page. Every element ought to have a take a look at file to go alongside them.

App.take a look at.tsx

import { render, display } from '@testing-library/react';

import App from './App';

describe('<App />', () => {
    it('has a following textual content label', () => {
        render(<App />);

        const el = display.getByText(/Following/i);

        anticipate(el).toBeTruthy();
    });

    it('has a followers textual content label', () => {
        render(<App />);

        const el = display.getByText(/Followers/i);

        anticipate(el).toBeTruthy();
    });

    it('has a you would possibly like heading', () => {
        render(<App />);

        const el = display.getByText(/You would possibly like/i);

        anticipate(el.innerHTML).toBe('You would possibly like');
    });

    it('has a whats occurring heading', () => {
        render(<App />);

        const el = display.getByText(/Whats occurring/i);

        anticipate(el.innerHTML).toBe('Whats occurring');
    });
});
Enter fullscreen mode

Exit fullscreen mode



Finish-To-Finish Testing with Cypress

This Cypress take a look at will routinely put up 3 tweets. It is all carried out in actual time and the tweets will present up in your database and on the reside software.

cypress/integratioin/tweet.spec.js

describe('person type move', () => {
    beforeEach(() => {
        cy.viewport(1600, 900);

        cy.go to('http://localhost:3000/');
    });

    it('person posts a tweet', () => {
        // Publish a tweet

        cy.get('.compose-tweet-btn').click on();

        cy.get('textarea[name="tweet"]').sort(
            'What occurred to all that enjoyable you had been having?! Come on, lets attempt to take pleasure in this!'
        );

        cy.wait(3000);

        cy.get('.post-tweet-btn').click on();
    });

    it('person posts a second tweet', () => {
        // Publish a tweet

        cy.get('.compose-tweet-btn').click on();

        cy.get('textarea[name="tweet"]').sort('That was an Assault on Titan easter egg πŸ₯š πŸ˜„');

        cy.wait(3000);

        cy.get('.post-tweet-btn').click on();
    });

    it('person posts a 3rd tweet', () => {
        // Publish a tweet

        cy.get('.compose-tweet-btn').click on();

        cy.get('textarea[name="tweet"]').sort(
            'The Rumbling arrives on Marley 😱 https://www.youtube.com/watch?v=wT2H68kEmi8'
        );

        cy.wait(3000);

        cy.get('.post-tweet-btn').click on();
    });
});
Enter fullscreen mode

Exit fullscreen mode



Deployment

When you could have accomplished constructing your software the ultimate step is deployment. You might want to get your software on-line so that everybody can see it. There are dozens of platforms on the market however listed here are my prime 5 platforms in no specific order.

  1. Netlify
  2. Vercel
  3. Heroku
  4. DigitalOcean
  5. AWS



Remaining Ideas

We coated all the MERN stack together with TypeScript, SQL, Take a look at Pushed Improvement, Finish to Finish Testing and even Docker! Congratulations you simply turned tremendous superior since you boosted your abilities and job prospects πŸ”₯πŸš€

Mess around with the databases and React frontend there may be a lot you are able to do with it. Like for instance creating extra Storybook parts, integration checks, including the performance to edit tweets and getting media like photographs and video to point out up within the tweets.

Add a Comment

Your email address will not be published. Required fields are marked *