0% found this document useful (0 votes)
9 views13 pages

Full Stack Assessment2 Key

The document outlines an assessment for a Full Stack Technologies course at Anna University, detailing various tasks related to React, Express.js, and MongoDB. It includes questions on React components, lifecycle methods, Express.js server creation, and user registration systems, along with code examples for each task. Additionally, it covers the creation of a Cricket Match Predictor app and a Book Tracker app, emphasizing the use of React for frontend development and Express for backend functionalities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views13 pages

Full Stack Assessment2 Key

The document outlines an assessment for a Full Stack Technologies course at Anna University, detailing various tasks related to React, Express.js, and MongoDB. It includes questions on React components, lifecycle methods, Express.js server creation, and user registration systems, along with code examples for each task. Additionally, it covers the creation of a Cricket Match Predictor app and a Book Tracker app, emphasizing the use of React for frontend development and Express for backend functionalities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

ANNA UNIVERSITY

DEPARTMENT OF COMPUTER TECHNOLOGY


CS23403 FULL STACK TECHNOLOGIES
Assessment II
Time: 90 minutes Total Marks: 50 Date: 21/04/2025
Part A (5 X 2=10)

1. What are React components? State the difference between a functional component and a
class component.

React components are independent, reusable pieces of code that return HTML via a render
function. They serve as the building blocks of any React application, enabling us to split the
UI into separate, reusable pieces that can be developed and maintained independently.

Functional Component: are JavaScript functions that accept props and return React elements
function Greet(props){
return <h1> Hello, {props.Name}! </h1>;
}
Class Components
Explicit lifecycle methods
More verbose
Complex inheritance
Functional Components (Hooks)
More concise
Easier to understand
Functional approach
Better performance
2. Create a simple form component with a text input and a submit button. When submitted,
display the entered text below the form.
import k{ useState } from 'react';
function Form() {
const [input,val setInput] = useState('');
const [submitText, setSubmitText] = useState('');
const submit = (e) => {
setSubmittext(inputValue);
};
return (
<div>
<form onSubmit={submit}>
<input
type="text"
value={inputval}
onChange={(e) => setInput(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
<h1>{submitText}</h1>
</div>
);
}
export default Form;

3. What is Express.js?
Express.js is a web application framework of node.js that provides a robust set of features to
build web applications and APIs.
4. Write an Express.js code to create a simple server with an endpoint /add-user. This endpoint
should accept a POST request with a JSON body containing a user's name and age, and
store this data in an in-memory array.
const express = require('express');
const app = express();

app.use(express.json());
const PORT=3000;
let users = [];

app.post('/add-user', (req, res) => {


const { name, age } = req.body;
users.push({ name, age });
res.send('User added');
});

app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});

5. State the difference between MongoDB and relational databases in terms of data structure
and schema? write a Todo schema with title and description in both MongoDB Shell and
Express (Mongoose).
MongoDB
Structure: Collections
Schema: Flexible
Data format: BSON/JSON. { TITLE: “Learn MongoDB”; DESCRIPTION: “Understand and
practice”}
Relational Database
Structure: Table(rows and columns)
Schema: Fixed
Data format: Typed fields. Title Varchar2(20), Description varchar2(50);
MangoDBshell
db.createCollection("todos", {
title: { bsonType: "string" },
description: { bsonType: "string" }
});
Express
const mongoose = require('mongoose');
const todoSchema = new mongoose.Schema({
title: String,
description: String
});
const Todo = mongoose.model('Todo', todoSchema);

Part B(2 X 12=24)

6. Discuss the three phases of a React component's lifecycle and list the corresponding
methods in class components vs. functional components with hooks (4 Marks)
Explain the React component lifecycle in the CartComponent by adding items to the cart
using useEffect. How does the first useEffect simulate the mount and unmount phases, and
how does the second useEffect handle updates when items are added to the cart?(4 Marks)
What is React.memo? Explain how wrapping a child component (CartItem) in React.memo
can improve performance in CartComponent. 4 Marks)

Class Components:

Mounting: componentDidMount()
Updating: componentDidUpdate()
Unmounting: componentWillUnmount()

Functional Components with Hooks:

Mounting: useEffect(() => {}, [])


Updating: useEffect(() => {}, [state])
Unmounting: useEffect(() => { return () => {} }, [])

import React, { useState, useEffect } from 'react';


function Cart() {
const [cartItems, setCartItems] = useState([]);
// Mount and Unmount phase
useEffect(() => {
console.log('Cart component started'); // when component mounts
return () => {
console.log('Cart component removed'); // when component unmounts
};
}, []);
// Updates phase
useEffect(() => {
console.log('Cart items changed:', cartItems.length);
}, [cartItems]);
function addItem() {
const newItem = { name: 'Laptop', price: 150000 };
setCartItems([...cartItems, newItem]);
};
return (
<div>
<h2>Cart Items</h2>
<button onClick={addItem}>Add Item</button>
<p>Items in cart: {cartItems.length}</p>
</div>
);
}
React.memo is used to wrap the Child component, which prevents unnecessary re-renders
when its props haven't changed.

import React, { useState, memo } from 'react';


function Cart() {
const [cart, setCart] = useState("Cart rendered");
const [cartItems] = useState([{ name: 'Apple Phone', price: 50000 }]);
function updateCart() {
setCart("Cart getting Re-rendered"); }
return (
<div>
<button onClick={updateCart}> UpdateCart </button>
<h1>{cart}</h1>
<CartItem item={cartItems[0]} />
</div>
);}
// Wrap the CartItem component with React.memo to avoid rerender of the child component
when parent rerenders
const CartItem=function CartItem({ item }) {
console.log('CartItem rendered');
return (
<div>
<h3>Name:{item.name}</h3>
<p>Price:{item.price}</p>
</div>
);}
export default Cart;

(or)
7. Explain the React Router for navigation between the Product List and Cart pages, using the
CardLayout wrapper and useState for managing state?
Create a Product List page that displays product names and prices, using useState to
manage the cart and allowing users to add products to the cart. Create an Add to Cart page
that lists the items in the cart, including product names, prices, and quantities, using useState
to manage cart items. Wrap both pages in a CardLayout component for consistent design.
//APP.JSX
import ProductList from './router/ProductList'
import Cart from './router/Cart'
import {BrowserRouter, Routes, Route} from 'react-router-dom'
import Navbar from './router/Navbar'
import { useState } from 'react'

export default function App(){


const [cartItems, setCartItems] = useState([])

function addToCart(product) {
setCartItems([...cartItems, product])
}
return(
<div>
<BrowserRouter>
<Navbar/>
<Routes>
<Route path='/' element={<ProductList addToCart={addToCart}/>}></Route>
<Route path='/Cart' element={<Cart cartItems={cartItems}/>}></Route>
</Routes>
</BrowserRouter>
</div>
)
}
Navbar.jsx
import {Link} from 'react-router-dom'
export default function Navbar(){
return(
<div style={{padding: '20px', backgroundColor: 'black', color: 'white'}}>
<Link to='/' style={{color: 'white', padding: '10px'}}>Product List</Link>
<Link to='/Cart' style={{color: 'white', padding: '10px'}}>Cart</Link>
</div>
)
}

CardLayout.jsx
export default function CardLayout({ children }){
return(
<div style={{padding: '20px', border: '1px solid black', margin: '20px'}}>
{children}
</div>
)
}

Cart.jsx
export default function Cart({ cartItems }){
return(
<div>
<h2>Cart</h2>
{cartItems.map((item) => (
<div style={{padding: '10px', border: '1px solid gray', margin: '10px'}}>
<h3>Name : {item.name}</h3>
<p>Price: {item.price}</p>
</div>
))
}
</div>
)
}
Product.jsx
import { useState } from 'react'
import CardLayout from './CardLayout'

export default function ProductList({ addToCart }){


const [products] = useState([
{ name: 'Apple Laptop', price: 150000 }])
return(
<CardLayout>
<div>
<h2>Product List</h2>
{products.map((product) => (
<div style={{padding: '10px', border: '1px solid gray', margin: '10px'}}>
<h3>Name: {product.name}</h3>
<p>Price: {product.price}</p>
<button onClick={() => addToCart(product)} style={{padding: '5px'}}>
Add to Cart
</button>
</div>
))}
</div>
</CardLayout>
)
}

(12 Marks)
8. Write a user registration system with a React frontend and an Express backend. The frontend
should include a registration form with fields for username, email, password, and confirm
password, along with validation and a "Register" button that sends a POST request to
/api/register. Upon successful registration, the response should be displayed. Additionally,
implement a button to fetch registration statistics from /api/status, including total users and
the last registration time. The backend should handle the registration logic with validation for
username, email, and password, and return a response with success/error messages and
registration strength. It should also provide registration stats via /api/stats.

// App.js
import { useState } from 'react';

function App() {
const [uname, setname] = useState('');
const [email, setEmail] = useState('');
const [pwd, setPwdd] = useState('');
const [confirmPwd, setConfirmPwd] = useState('');
const [message, setMessage] = useState('');
const [stats, setStats] = useState('');

function handleRegister() {
let errors = [];
if (!uname || !email || !pwd || !confirmPwd) {
errors.push('All fields are required');
}

if (pwd && confirmPwd && pwd !== confirmPwd) {


errors.push('Passwords do not match');
}

if (password && password.length < 6) {


errors.push('Password too short');
}
if (errors.length > 0) {
setMessage(errors.join(', '));
return;
}

// Send POST request


fetch('http://localhost:3000/api/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({username: username,email: email,password: password

})
})
.then(response => response.json())
.then(data => {
console.log('Registration response:', data);
setMessage(data.message);
})
.catch(error => {
console.log('Error:', error);
setMessage('Registration failed');
});
}

// Fetch Stats
function fetchStats() {
fetch('http://localhost:3000/api/stats')
.then(response => response.json())
.then(data => {
console.log('Stats data:', data);
setStats(data);
})
.catch(error => {
console.log('Error fetching stats:', error);
setMessage('Fetch stats failed');
});
}

return (
<div style={{ padding: '20px' }}>
<h1>User Registration</h1>
<div><label>Username:</label>
<input type="text" value={uname} onChange={(e) => setname(e.target.value)}/>
</div>
<div><label>Email:</label>
<input type="text" value={email} onChange={(e) => setEmail(e.target.value)}/>
</div>
<div><label>Password:</label>
<input type="password" value={pwd} onChange={(e) =>
setPwd(e.target.value)}/></div>
<div> <label>Confirm Password:</label>
<input type="password" value={confirmPassword} onChange={(e) =>
setConfirmPwd(e.target.value)}/></div>

<button onClick={handleRegister}> Register </button>

<div> <p>{message}</p> </div>

<div> <button onClick={fetchStats}> Registration Stats </button>


<p>Total Users: {stats.totalUsers}</p>
<p>Last Registration: {stats.lastRegistration}</p>
</div>

</div>
);
}

export default App;


`// Backend - server/index.js
const express = require("express");
const cors = require("cors");
const app = express();

app.use(cors());
app.use(express.json());

// Simple in-memory storage (like your todo example)


let users = [];
let registrationStats = {
totalUsers: 0,
lastRegistration: null
};

// Registration endpoint
app.post("/api/register", (req, res) => {
try {
const { username, email, password } = req.body;

// Basic validation
if (!username || !email || !password) {
return res.json({
success: false,
message: "All fields are required"
});
}

// Check if username already exists


const existingUser = users.find(user => user.username === username);
if (existingUser) {
return res.json({
success: false,
message: "Username already exists"
});
}

// Check email format (simple check)


if (!email.includes('@')) {
return res.json({
success: false,
message: "Invalid email format"
});
}

// Password strength check


let strength = "Weak";
if (password.length >= 6) {
strength = "Medium";
}
if (password.length >= 8 && /[A-Z]/.test(password) && /[0-9]/.test(password)) {
strength = "Strong";
}
// Add new user
const newUser = {
id: users.length + 1,
username: username,
email: email,
password: password, // In real app, hash this!
registeredAt: new Date()
};

users.push(newUser);

// Update stats
registrationStats.totalUsers = users.length;
registrationStats.lastRegistration = new Date().toLocaleString();

console.log('New user registered:', newUser);


console.log('Current users:', users.length);

res.json({
success: true,
message: `Registration successful! Password strength: ${strength}`,
strength: strength
});

} catch (error) {
console.log('Registration error:', error);
res.json({
success: false,
message: "Registration failed"
});
}
});

// Stats endpoint
app.get("/api/stats", (req, res) => {
try {
res.json({
totalUsers: registrationStats.totalUsers,
lastRegistration: registrationStats.lastRegistration || "No registrations yet"
});
} catch (error) {
console.log('Stats error:', error);
res.json({
error: "Failed to get stats"
});
}
});
(or)

9. Create an Cricket Match Predictor app where users predict the match winner. The user
should input the names of two teams, predict the winner, and provide predicted scores for
both teams. The app should include a form with fields for the two teams, predicted scores,
and a dropdown to select the winner. Once the prediction is submitted, the server generates
random predictions for the winner and the scores for fun. The backend updates the actual
results and shows a comparison with the user’s and server’s predictions.

Part C (16 MARKS)

10. Create a Book Tracker app using React and Express where users manage their reading list.
The React form collects book title, author, genre, and rating. Users can add new books via a
POST request to /api/AddBooks and view all books using a GET request to /api/GetBooks.
The Express backend handles these requests and stores book data in MongoDB. Users can
also edit or delete books through corresponding PUT and DELETE endpoints. The React app
should update the book list dynamically after each action. Filtering options by genre or rating
should be supported as query parameters in the GET request.
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');

const app = express();


app.use(express.json());
app.use(cors());
mongoose.connect('mongodb://localhost:27017/bookdb');

const Book = mongoose.model('Book', {


title: String,
author: String,
genre: String,
rating: Number
});

app.post('/api/GetBooks', async (req, res) => {


const books = await Book.find(req.body);
res.json(books);
});

app.post('/api/AddBooks', async (req, res) => {


const book = new Book(req.body);
await book.save();
res.json(book);
});

app.put('/api/books/:id', async (req, res) => {


const book = await Book.findByIdAndUpdate(req.params.id, req.body, {new: true});
res.json(book);
});

app.delete('/api/books/:id', async (req, res) => {


await Book.findByIdAndDelete(req.params.id);
res.json({message: 'deleted'});
});

app.listen(3000, () => console.log('Server on port 3000'));

import React, { useState, useEffect } from 'react';

export default function BookTracker() {


const [books, setBooks] = useState([]);
const [title, setTitle] = useState('');
const [author, setAuthor] = useState('');
const [genre, setGenre] = useState('');
const [rating, setRating] = useState('');
const [edit, setEdit] = useState(null);

const getBooks = async () => {


const res = await fetch('/api/GetBooks', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({})
});
const data = await res.json();
setBooks(data);
};

const addBook = async () => {


if (!title || !author) return;
await fetch('/api/AddBooks', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({title, author, genre, rating})
});
reset();
getBooks();
};

const updateBook = async () => {


await fetch(`/api/books/${edit}`, {
method: 'PUT',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({title, author, genre, rating})
});
reset();
getBooks();
};

const deleteBook = async (id) => {


await fetch(`/api/books/${id}`, {method: 'DELETE'});
getBooks();
};

const editBook = (book) => {


setTitle(book.title);
setAuthor(book.author);
setGenre(book.genre);
setRating(book.rating);
setEdit(book._id);
};

return (
<div>
<h1>Book Tracker</h1>
<div>
<input placeholder="Title" value={title} onChange={(e) => setTitle(e.target.value)} />
<input placeholder="Author" value={author} onChange={(e) => setAuthor(e.target.value)}
/>
<input placeholder="Genre" value={genre} onChange={(e) => setGenre(e.target.value)} />
<input placeholder="Rating" value={rating} onChange={(e) => setRating(e.target.value)} />
<button onClick={edit }</button
<button onClick={updateBook}</button<button onClick={AddBook }</button>
<button onClick={deleteBook}</button><button onClick={getBooks}</button
</div>
<div>
{books.map(book => (
<div key={book._id}>
<h3>{book.title}</h3>
<p>{book.author}</p>
<p>{book.genre}</p>
<p>Rating: {book.rating}</p>
</div>
))}
</div>
</div>
);
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy