Creating A Student Register Using React
Creating A Student Register Using React
Introduction
Building a student register is a common requirement for educational institutions and related
applications. Combining Laravel for the backend and React for the frontend leverages the
strengths of both frameworks, providing a robust, scalable, and dynamic application. Laravel
offers a powerful API-building capability, while React ensures a responsive and interactive
user interface. This guide walks you through creating a comprehensive student registration
system using Laravel and React, covering everything from initial setup to deployment.
Prerequisites
Before embarking on this project, ensure you have the following tools and knowledge:
Optional but beneficial: Familiarity with RESTful APIs, Axios for HTTP requests in React,
and basic understanding of authentication mechanisms.
Setting Up the Laravel Backend
1. Install Laravel
cd student-register-backend
2. Configure Environment
cp .env.example .env
Laravel Sanctum provides a featherweight authentication system for SPAs (single page
applications):
Run migrations:
To allow your React frontend to communicate with the Laravel backend, configure CORS.
return [
'max_age' => 0,
];
Choose a relational database system like MySQL. Ensure it's installed and running.
2. Create Database
3. Configure .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=student_register
DB_USERNAME=your_username
DB_PASSWORD=your_password
• Students Table:
o id (primary key)
o first_name
o last_name
o email
o phone
o address
o date_of_birth
o created_at
o updated_at
5. Create Migration
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
protected $fillable = [
'first_name',
'last_name',
'email',
'phone',
'address',
'date_of_birth',
];
}
use App\Http\Controllers\API\StudentController;
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('students', StudentController::class);
});
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\Student;
use Illuminate\Http\Request;
$student->update($request->all());
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('student-register-token')-
>plainTextToken;
return response()->json([
'user' => $user,
'token' => $token,
], 201);
}
// User Login
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required|string',
]);
$token = $user->createToken('student-register-token')-
>plainTextToken;
return response()->json([
'user' => $user,
'token' => $token,
], 200);
}
// User Logout
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json([
'message' => 'Logged out successfully.'
], 200);
}
}
c. Define Authentication Routes
use App\Http\Controllers\API\AuthController;
Route::middleware('auth:sanctum')->post('/logout', [AuthController::class,
'logout']);
cd student-register-frontend
Install Axios for HTTP requests and React Router for routing:
import 'bootstrap/dist/css/bootstrap.min.css';
src/
│
├── components/
│ ├── Auth/
│ │ ├── Login.js
│ │ └── Register.js
│ ├── Students/
│ │ ├── StudentList.js
│ │ ├── StudentForm.js
│ │ └── StudentDetail.js
│ └── Layout/
│ └── Navbar.js
│
├── services/
│ └── api.js
│
├── App.js
├── index.js
└── ...
4. Configure Axios
// src/services/api.js
Create src/components/Layout/Navbar.js:
// src/components/Layout/Navbar.js
return (
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link className="navbar-brand" to="/">Student Register</Link>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
{isLoggedIn && (
<li className="nav-item">
<Link className="nav-link"
to="/students">Students</Link>
</li>
)}
</ul>
<ul className="navbar-nav ml-auto">
{isLoggedIn ? (
<li className="nav-item">
<button className="btn btn-link nav-link"
onClick={handleLogout}>Logout</button>
</li>
) : (
<>
<li className="nav-item">
<Link className="nav-link"
to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link"
to="/register">Register</Link>
</li>
</>
)}
</ul>
</div>
</nav>
);
};
Create src/components/Auth/Register.js:
// src/components/Auth/Register.js
return (
<div className="container mt-5">
<h2>Register</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Name</label>
<input type="text" name="name" className="form-control"
value={form.name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" name="password" className="form-
control" value={form.password} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Confirm Password</label>
<input type="password" name="password_confirmation"
className="form-control" value={form.password_confirmation}
onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-
primary">Register</button>
</form>
</div>
);
};
Create src/components/Auth/Login.js:
// src/components/Auth/Login.js
return (
<div className="container mt-5">
<h2>Login</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" name="password" className="form-
control" value={form.password} onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-
primary">Login</button>
</form>
</div>
);
};
Create src/components/Students/StudentList.js:
// src/components/Students/StudentList.js
useEffect(() => {
fetchStudents();
}, []);
return (
<div className="container mt-5">
<h2>Students</h2>
<Link to="/students/create" className="btn btn-primary mb-
3">Add New Student</Link>
<table className="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{students.map(student => (
<tr key={student.id}>
<td>{student.id}</td>
<td>{student.first_name}
{student.last_name}</td>
<td>{student.email}</td>
<td>{student.phone}</td>
<td>
<Link to={`/students/${student.id}`}
className="btn btn-info btn-sm mr-2">View</Link>
<Link to={`/students/edit/${student.id}`}
className="btn btn-warning btn-sm mr-2">Edit</Link>
<button className="btn btn-danger btn-sm"
onClick={() => handleDelete(student.id)}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
{renderPagination()}
</div>
);
};
Create src/components/Students/StudentForm.js:
// src/components/Students/StudentForm.js
useEffect(() => {
if (isEdit) {
API.get(`/students/${id}`)
.then((response) => {
setForm(response.data);
})
.catch((error) => {
console.error('Error fetching student:', error);
});
}
}, [id, isEdit]);
const handleChange = (e) => {
setForm({...form, [e.target.name]: e.target.value});
};
return (
<div className="container mt-5">
<h2>{isEdit ? 'Edit' : 'Add'} Student</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" name="first_name" className="form-
control" value={form.first_name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" name="last_name" className="form-
control" value={form.last_name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Phone</label>
<input type="text" name="phone" className="form-
control" value={form.phone} onChange={handleChange} />
</div>
<div className="form-group">
<label>Address</label>
<textarea name="address" className="form-control"
value={form.address} onChange={handleChange}></textarea>
</div>
<div className="form-group">
<label>Date of Birth</label>
<input type="date" name="date_of_birth"
className="form-control" value={form.date_of_birth} onChange={handleChange}
/>
</div>
<button type="submit" className="btn btn-success">{isEdit ?
'Update' : 'Save'}</button>
</form>
</div>
);
};
Create src/components/Students/StudentDetail.js:
// src/components/Students/StudentDetail.js
useEffect(() => {
API.get(`/students/${id}`)
.then((response) => {
setStudent(response.data);
})
.catch((error) => {
console.error('Error fetching student:', error);
});
}, [id]);
if (!student) {
return <div className="container mt-5">Loading...</div>;
}
return (
<div className="container mt-5">
<h2>Student Details</h2>
<div className="card">
<div className="card-body">
<h5 className="card-title">{student.first_name}
{student.last_name}</h5>
<p className="card-text"><strong>Email:</strong>
{student.email}</p>
<p className="card-text"><strong>Phone:</strong>
{student.phone || 'N/A'}</p>
<p className="card-text"><strong>Address:</strong>
{student.address || 'N/A'}</p>
<p className="card-text"><strong>Date of
Birth:</strong> {student.date_of_birth || 'N/A'}</p>
<Link to="/students" className="btn btn-primary">Back
to List</Link>
</div>
</div>
</div>
);
};
Edit src/App.js:
// src/App.js
return (
<Router>
<Navbar />
<Switch>
<Route exact path="/">
<Redirect to="/students" />
</Route>
<Route path="/register">
{isLoggedIn ? <Redirect to="/students" /> : <Register
/>}
</Route>
<Route path="/login">
{isLoggedIn ? <Redirect to="/students" /> : <Login />}
</Route>
<Route exact path="/students">
{isLoggedIn ? <StudentList /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/create">
{isLoggedIn ? <StudentForm /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/edit/:id">
{isLoggedIn ? <StudentForm /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/:id">
{isLoggedIn ? <StudentDetail /> : <Redirect to="/login"
/>}
</Route>
<Route path="*">
<div className="container mt-5">
<h2>404 - Not Found</h2>
<p>The page you are looking for does not exist.</p>
</div>
</Route>
</Switch>
</Router>
);
};
// src/components/Layout/Navbar.js
return (
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link className="navbar-brand" to="/">Student Register</Link>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
{isLoggedIn && (
<li className="nav-item">
<Link className="nav-link"
to="/students">Students</Link>
</li>
)}
</ul>
<ul className="navbar-nav ml-auto">
{isLoggedIn ? (
<li className="nav-item">
<button className="btn btn-link nav-link"
onClick={handleLogout}>Logout</button>
</li>
) : (
<>
<li className="nav-item">
<Link className="nav-link"
to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link"
to="/register">Register</Link>
</li>
</>
)}
</ul>
</div>
</nav>
);
};
• Navigate to /students/create.
• Fill out the form and submit.
• The student will be added to the database and appear in the student list.
• Navigate to /students.
• View the list of students with pagination.
• Click on a student's "View" button to see detailed information.
• Navigate to /students/edit/{id}.
• Modify the desired fields and submit.
• The changes will reflect in the student list and detail view.
Ensure that only authenticated users can access certain routes. This is handled both in the
frontend (React) and backend (Laravel).
• Frontend: Use React Router to redirect unauthenticated users to the login page.
• Backend: Use Laravel Sanctum's auth:sanctum middleware to protect API routes.
3. Validating Inputs
Both frontend and backend should validate user inputs to prevent malicious data from being
processed.
4. Error Handling
5. Implementing HTTPS
Ensure that your application uses HTTPS to encrypt data transmitted between the client and
server.
Testing and Deployment
1. Testing the Application
a. Backend Testing
// tests/Feature/StudentTest.php
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->postJson('/api/students', [
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => '[email protected]',
]);
$response->assertStatus(201)
->assertJson([
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => '[email protected]',
]);
$this->assertDatabaseHas('students', [
'email' => '[email protected]',
]);
}
Run tests:
Use Jest and React Testing Library to write tests for your React components.
// src/components/Auth/Login.test.js
jest.mock('../../services/api');
expect(screen.getByLabelText(/Email/i)).toBeInTheDocument();
expect(screen.getByLabelText(/Password/i)).toBeInTheDocument();
});
render(
<BrowserRouter>
<Login />
</BrowserRouter>
);
fireEvent.click(screen.getByText(/Login/i));
Run tests:
npm test
2. Deployment
a. Deploy Laravel Backend
1. Choose a Hosting Provider: Options include DigitalOcean, AWS, Heroku, Laravel Forge, etc.
2. Server Setup:
o Install necessary software: PHP, Composer, Nginx/Apache, MySQL, etc.
3. Clone Repository:
o Use Git to clone your project to the server.
4. Install Dependencies:
5. composer install
6. Configure Environment:
o Set up the .env file with production credentials.
7. Run Migrations and Seeders:
8. php artisan migrate --force
9. php artisan db:seed --force
10. Set Permissions:
11. sudo chown -R www-data:www-data /path-to-your-project
12. sudo chmod -R 775 storage
13. sudo chmod -R 775 bootstrap/cache
14. Configure Web Server:
o Set up Nginx or Apache to serve the Laravel application.
15. Set Up SSL:
o Use Let's Encrypt or another provider to secure your application with HTTPS.
1. Choose a Hosting Provider: Options include Netlify, Vercel, AWS Amplify, GitHub Pages, etc.
2. Build the React App:
3. npm run build
4. Deploy the Build Folder:
o Upload the build folder to your chosen hosting provider.
5. Configure Environment Variables:
o Ensure the React app points to the correct backend API URL.
6. Set Up Routing:
o Configure the hosting provider to handle client-side routing (e.g., redirect all routes
to index.html).
Conclusion
Creating a student register application using React for the frontend and Laravel for the
backend combines the strengths of both technologies, resulting in a robust, scalable, and user-
friendly system. Laravel handles the server-side logic, API creation, and database
interactions, while React provides a dynamic and responsive user interface. By following this
comprehensive guide, you can develop a full-stack application that efficiently manages
student data with secure authentication, seamless CRUD operations, and a polished user
experience.
Additional Resources:
• Laravel Documentation
• React Documentation
• Laravel Sanctum Documentation
• Axios Documentation
• React Router Documentation
• Bootstrap Documentation
Feel free to explore these resources to deepen your understanding and enhance your
application further.