I’ve developed a React application for a book library based on what I learned in my university classes. The application manages a list of books, allowing users to view, rate, and delete books. I’ve structured my components as follows:
- App.js (main component)
- BookTable (renders the table of books)
- BookTableRow (renders each row in the table)
- StarRating (handles the star rating for each book)
- Star (individual star component)
- StarRating (handles the star rating for each book)
- BookTableRow (renders each row in the table)
- BookTable (renders the table of books)
(App.js)
import './App.css';
import React, { useState, useEffect } from 'react';
import {books as bks} from './services/bookObject';
import BookTable from './components/bookTable';
function App() {
const [books, updateBooks] = useState(bks);
const initProcess = () => {
const booksCurrent = books.map(book => ({
...book,
rating: 0
}));
updateBooks(booksCurrent);
};
// execute only one time at first render
useEffect(() => {
initProcess();
}, []);
const handleDelete = (id) => {
const booksCurrent = books.filter(book => book._id != id);
updateBooks(booksCurrent);
};
const handleRating = (id, rating) => {
const booksCurrent = books.map(book => {
if (book._id === id) {
book.rating = rating;
}
return book;
});
updateBooks(booksCurrent);
console.log(books);
}
return (
<div className="App">
<h1>My Book Library</h1>
<p>Showing {books.length} books</p>
<BookTable
books={books}
handleDelete={handleDelete}
handleRating={handleRating}/>
</div>
);
}
export default App;
(components/bookTable.jsx)
import React, { Component } from 'react';
import BookTableRow from './bookTableRow';
const BookTable = ({books, handleDelete = f => f, handleRating = f => f}) => {
if (books.length === 0) {
return (<p>There is no book infromation</p>);
}
return (
<div className='books'>
<table className="table">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Category</th>
<th>Author</th>
<th>Number In Stock</th>
<th>Price</th>
<th>Year</th>
<th>Review</th>
<th>Action(s)</th>
</tr>
</thead>
<tbody>
{
books.map((book, index) => (
<BookTableRow
book={book}
onDelete={handleDelete}
onRating={handleRating}
/>
))
}
</tbody>
</table>
</div>
);
}
export default BookTable;
(components/bookTableRow.jsx)
import * as React from 'react';
import { Component } from 'react';
import StarRating from './starRating';
const BookTableRow = ({book, onDelete = f => f, onRating = f => f}) => {
return (
<tr>
<td>{book._id}</td>
<td>{book.title}</td>
<td>{book.category.name}</td>
<td>{book.author}</td>
<td>{book.numberInStock}</td>
<td>{book.price}</td>
<td>{book.publishYear}</td>
<td>
<StarRating
starCount={5}
book={book}
onRating={onRating}
/></td>
<td>
<button className="btn btn-danger" onClick={() => onDelete(book._id)}>Delete</button>
</td>
</tr>
);
}
export default BookTableRow;
(components/starRating.jsx)
import React, { Component, useState } from 'react';
import { FaStar } from 'react-icons/fa';
import { createArray } from '../services/createArray';
import Star from './star';
const StarRating = ({starCount, book, onRating = f => f}) => {
return (
<div>
{
createArray(starCount).map((n, i) => (
<Star
book={book}
index={i}
isSelected={i < book.rating+1}
onClick={onRating}
/>
))
}
<p> {book.rating+1} of {starCount} stars</p>
</div>
);
}
export default StarRating;
(components/star.jsx)
import React, { useState } from 'react';
import { FaStar } from 'react-icons/fa';
const Star = ({book, index, isSelected, onClick = f => f}) => {
return (
<div>
<FaStar color={isSelected?"red": "gray"} onClick={() => onClick(book._id, index)}/>
</div>
);
}
export default Star;
services/bookObject.js
books = [
(the list of book object)
]
export function getBooks() {
return books;
}
(services/createArray.js)
import React, { Component } from 'react';
export const createArray = (length) => {
return ([...Array(length)]);
}
My questions are:
- Is this level of component nesting (App > BookTable > BookTableRow > StarRating > Star) considered good practice in professional React development?
- Are there any potential issues or drawbacks with this approach?
- How might experienced React developers structure this differently, if at all?
- Are there any general guidelines for deciding when to create a new component versus keeping functionality in a parent component?
I’m looking to understand best practices in React component structuring as I transition from academic projects to professional development. Any insights or suggestions for improvement would be greatly appreciated.