Site icon Bệ Phóng Việt

ReactJS sử dụng Route và form để đăng ký account và đăng nhập

Advertisements

Trong bài viết này, bạn sẽ học cách viết 1 reactjs web app đơn giản. App này sẽ có các chức năng sau:

  1. Đăng ký tài khoảng (account)
  2. Đăng nhập (authentication/login)
  3. Cập nhật mật khẩu (change password)

App sẽ gọi RESTful Web Service API mà chúng ta đã viết ở bài Xây Dựng RESTful Web Service (Laravel).

Phiên bản sử dụng

Web app của chúng ta sẽ dùng các package sau:

  1. ReactJS 18.2
  2. Bootstrap 5
  3. React router dom: 6.2
  4. Anxios 1.2.2

Sau khi tạo dự án reactjs (xem hướng dẫn), bạn hãy chạy các lệnh sau để cài react router, axios và bootstrap:

npm install react-router-dom@6.2.0
npm install axios
npm install bootstrap 

Tạo component Menu

Menu chính của app sẽ gồm có tên app, Home, Register và Login. Menu này sẽ có thể sử dụng ở tất cả các màn hình của app, giúp cho việc navigate được tiện lợi hơn cho người sử dụng.

Bạn có thể tạo thư mục src/components/ và đặt file Menu.js vào thư mục này với nội dung như sau:

import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';

function Menu() {
  return (
    <div>
      <nav className="navbar navbar-expand-lg navbar-light bg-light">
        <a className="navbar-brand" href="#">My App</a>
        <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
          <span className="navbar-toggler-icon"></span>
        </button>
        <div className="collapse navbar-collapse" id="navbarNav">
        <ul className="navbar-nav">
          <li className="nav-item active">
            <a className="nav-link" href="/">Home</a>
          </li>
          <li className="nav-item">
            <a className="nav-link" href="/register">Register</a>
          </li>
          <li className="nav-item">
            <a className="nav-link" href="#">Login</a>
          </li>
        </ul>
       </div>
     </nav>
    </div>
  );
}

export default Menu;
  1. Đoạn code trên là một component Menu trong ReactJS, dùng để tạo một top menu bao gồm các menu item “Home”, “Register” và “Login”.
  2. Sau đó, có dòng import 'bootstrap/dist/css/bootstrap.min.css'; dùng để import file CSS của Bootstrap vào component.
  3. Component Menu sử dụng HTML và Bootstrap để tạo top menu bao gồm các menu item “Home”, “Register” và “Login”. Các menu item này sẽ được hiển thị trên navbar và có thể được click để chuyển đến các trang khác (chúng ta sẽ khai báo các đường link này ở dạng Route ở mục cuối bài này).
  4. Cuối cùng, component Menu sử dụng export default Menu; để cho phép component này được import và sử dụng ở bất cứ nơi nào trong app.

Tạo component Home

Home sẽ là component cho trang đầu tiên của app khi người sử dụng vào trang web.  đặt file Home.js có nội dung như sau vào file này:

import React, { Component } from 'react';
import axios from 'axios';
import Menu from './Menu';

class Home extends Component {
  constructor(props) {
    super(props);

      this.state = {

      };
  }

  render() {
    return (
      <div class="container">
        <Menu />
        <h1>Welcome to My App</h1>
      </div>

    );
  }
}

export default Home;
  1. Đoạn code trên là một component Home trong ReactJS, dùng để tạo trang chủ của app.
  2. Trong component Home, đầu tiên có dòng import React, { Component } from 'react'; dùng để import React và class Component từ thư viện React.
  3. Sau đó, có dòng import Menu from './Menu'; dùng để import component Menu chúng ta vừa tạo ở mục trước vào Home.
  4. Cuối cùng, component Home được viết dưới dạng class component với các phương thức constructorrender. Trong phương thức constructor, bạn có thể khai báo các thuộc tính của component và khởi tạo giá trị cho chúng bằng this.state. Trong phương thức render, bạn có thể viết nội dung HTML của component và sử dụng các thuộc tính của component để hiển thị nội dung tương ứng.

Tạo component RegisterForm

Đặt file RegisterForm.js vào thư mục component với nội dung sau:

import React, { Component } from 'react';
import axios from 'axios';
import Menu from './Menu';

class RegisterForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      name: '',
      email: '',
      password: '',
      password_confirmation: '',
      message: '',
      errorMessage: ''
    };
  }

  handleSubmit = (event) => {
    event.preventDefault();

    axios.post('http://localhost:8000/api/user/register', {
      name: this.state.name,
      email: this.state.email,
      password: this.state.password,
      password_confirmation: this.state.password_confirmation
    })
      .then(response => {
        this.setState({
          message: 'Account registered. Please check your email for verification instructions.'
        });
      })
      .catch(error => {
        console.error(error);
        this.setState({
          errorMessage: 'Something went wrong'
        });
      });
  }

  render() {
    return (
      <div class="container">
        <Menu />
        <form onSubmit={this.handleSubmit}>
          {this.state.message && <p className="text-success">{this.state.message}</p>}
          {this.state.errorMessage && <p className="text-error">{this.state.errorMessage}</p>}
          <div className="form-group">
            <label htmlFor="name">Name</label>
            <input type="text" className="form-control" id="name" value={this.state.name} onChange={event => this.setState({ name: event.target.value })} />
          </div>
          <div className="form-group">
            <label htmlFor="email">Email</label>
            <input type="email" className="form-control" id="email" value={this.state.email} onChange={event => this.setState({ email: event.target.value })} />
          </div>
          <div className="form-group">
            <label htmlFor="password">Password</label>
            <input type="password" className="form-control" id="password" value={this.state.password} onChange={event => this.setState({ password: event.target.value })} />
          </div>
          <div className="form-group">
            <label htmlFor="password_confirmation">Password</label>
            <input type="password" className="form-control" id="password_confirmation" value={this.state.password_confirmation} onChange={event => this.setState({ password_confirmation: event.target.value })} />
          </div>
          <button type="submit" className="btn btn-primary">Register</button>
        </form>
      </div>
    );
  }
}

export default RegisterForm;
  1. Trong đoạn code này, phương thức render hiển thị một form với các input field cho người dùng nhập tên, email, mật khẩu và xác nhận mật khẩu. Khi người dùng nhập vào các input field, giá trị của chúng sẽ được lưu vào state của component.
  2. Cuối form có một nút Submit để gửi request đăng ký tài khoản mới đến server bằng axios. Web Service API này đã được viết ở bài trước. Bạn có thể tham khảo tại đây.
  3. Khi người dùng click nút Submit, sẽ gọi phương thức handleSubmit
  4. Phương thức handleSubmit là một hàm sử dụng để xử lý sự kiện khi người dùng submit form đăng ký tài khoản mới. Trong phương thức handleSubmit, hàm event.preventDefault() được gọi để ngăn chặn sự kiện submit mặc định của form, đồng thời gửi request đến server bằng axios để đăng ký tài khoản mới.

    Sau khi gửi request, hàm then sẽ được gọi nếu request thành công và trả về một response từ server. Trong trường hợp này, hàm then sẽ cập nhật thuộc tính message của state với giá trị “Account registered. Please check your email for verification instructions.” để hiển thị cho người dùng.

    Trong trường hợp request không thành công, hàm catch sẽ được gọi.

Update App.js

Khi vào app, chúng ta muốn người sử dụng sẽ được thấy trang Home đầu tiên. Trong App.js, hãy khai báo hiển thị Home.js component:

import './App.css';
import Home from './components/Home';
import React from 'react';


class App extends React.Component {
  constructor(props){
    super(props);
 
  }

  render() {
    return (
      <div>
        <Home />
      </div>

    );
  }
}

export default App;

Khai báo Route trong index.js

Gộp mọi thứ lại và cho phép reactjs biết chúng ta có các đường dẫn nào trong app này. Bạn phải khai báo router thì các menu trên Menu.js component mới hiển thị các trang như chúng ta mong muốn. Trong index.js, khai báo các route như sau:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import RegisterForm from './components/RegisterForm';

const routing = (
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App />} />
      <Route path="/register" element={<RegisterForm />} />
    </Routes>
  </BrowserRouter>
);
ReactDOM.render(
  routing,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Chạy app

Mở terminal và chạy lệnh

npm run 

Bạn sẽ thấy app được load ở đường dẫn hiển thị trong kết quả chạy. Thường là localhost:8000

Exit mobile version