[Vite+React]Active,inActive button[MacOS]

ReactExample6

๐Ÿ‘‰๐Ÿป ์•„๋ž˜๋Š” ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ํ”„๋ก ํŠธ์—”๋“œ(React)์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํƒœ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ ์ž…๋‹ˆ๋‹ค.
Below is the code that implements the function that changes the front-end (React) and database state when a button is clicked.

๐Ÿ‘‰๐Ÿป ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ / Create project

โœ”๏ธ Nodejs express server

% cd ReactExample6
% mkdir server
% cd server
% npm init -y
% npm install express
% npm install cors
% npm install pg

 โœ”๏ธ vite+react project(Frontend)

% npm create vite@latest client --template react-ts

๐Ÿ‘‰๐Ÿป 1. PostgreSQL ํ…Œ์ด๋ธ” ์ƒ์„ฑ / Create PostgreSQL table

โœ”๏ธ ๋จผ์ € ํ„ฐ๋ฏธ๋„์—์„œ psql์— ์ ‘์†ํ•œ ๋’ค, ๋ฒ„ํŠผ์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•  ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
First, connect to psql in the terminal and create a table to store the button state.

โœ”๏ธ postgresql ์ ‘์† / postgresql connection

% psql postgres

โœ”๏ธ ํ…Œ์ด๋ธ” ์ƒ์„ฑ / Create Table

CREATE TABLE button_status (
    id SERIAL PRIMARY KEY,
    is_active BOOLEAN NOT NULL DEFAULT false
);

-- ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์‚ฝ์ž… / Initial data insertion
INSERT INTO button_status (is_active) VALUES (false);

๐Ÿ‘‰๐Ÿป2. Express ์„œ๋ฒ„ ์„ค์ • (server.js) / Express server setup (server.js)

โœ”๏ธ server ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์— server.jsํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ  ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
Create a server.js file in the server directory and enter the code below.

โœ”๏ธpg ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค.
Communicate with the database using the pg library.

โœ”๏ธ MacOS์—์„œ postgresql ์„ค์ •์„ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ user๋Š” ์ž์‹ ์˜ MacOS๊ณ„์ •์ด๋ฉฐ ํŒจ์Šค์›Œ๋“œ๋Š” ๊ณต๋ฐฑ์ž…๋‹ˆ๋‹ค.
If you have not configured postgresql on MacOS, user is your MacOS account and password is blank.

const express = require('express');
const { Pool } = require('pg');
const cors = require('cors');

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

const pool = new Pool({
  user: 'yourid', // ๋ณธ์ธ์˜ ๊ณ„์ •๋ช… / Your account name
  host: 'localhost',
  database: 'postgres', // ๋ณธ์ธ์˜ DB๋ช… / Your DB name
  password: '', // ๋ณธ์ธ์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ / your password
  port: 5432,
});

// ํ˜„์žฌ ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ / Get current status
app.get('/status', async (req, res) => {
  try {
    const result = await pool.query('SELECT is_active FROM button_status WHERE id = 1');
    res.json(result.rows[0]);
  } catch (err) {
    res.status(500).send(err.message);
  }
});

// ์ƒํƒœ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ / Update your status
app.post('/toggle', async (req, res) => {
  const { isActive } = req.body;
  try {
    const result = await pool.query(
      'UPDATE button_status SET is_active = $1 WHERE id = 1 RETURNING *',
      [isActive]
    );
    res.json(result.rows[0]);
  } catch (err) {
    res.status(500).send(err.message);
  }
});

app.listen(3000, () => console.log('Server running on http://localhost:3000'));

โœ”๏ธ ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰๋˜๋Š”์ง€ ํ™•์ธ ํ•˜๊ธฐ / Check if the server is running

โญ๏ธ ์„œ๋ฒ„๊ฐ€ ๋ฐ”๋กœ ์‹คํ–‰ ์ข…๋ฃŒ๋˜๋ฉด ํฌํŠธ๋ฒˆํ˜ธ๋ฅผ ๋ฐ”๊พธ์„ธ์š” ์ €๋Š” 5000๋ฒˆ์“ฐ๋ฉด ์„œ๋ฒ„๊ฐ€ ์‹คํ–‰์ข…๋ฃŒ๋˜๋„ค์š”.
If the server stops running immediately, change the port number. When I use 5000, the server stops running.

% node server.js
Server running on http://localhost:3000

๐Ÿ‘‰๐Ÿป 3. Vite + React ํ”„๋ก ํŠธ์—”๋“œ (App.jsx) / Vite + React frontend (App.jsx)

โœ”๏ธ axios๋ชจ๋“ˆ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.( client/ )
Install the axios module ( client/ )

% npm install axios

โœ”๏ธ axios๋ฅผ ์‚ฌ์šฉํ•ด ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋ฉฐ ๋ฒ„ํŠผ์˜ UI๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.
Communicate with the server using axios and change the UI of the button.

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

function App() {
  const [isActive, setIsActive] = useState(false);

  // ์ฒ˜์Œ ๋กœ๋“œ๋  ๋•Œ ์„œ๋ฒ„์—์„œ ์ƒํƒœ ๊ฐ€์ ธ์˜ค๊ธฐ
  // Get state from server when first loaded
  useEffect(() => {
    axios.get('http://localhost:3000/status')
      .then(res => setIsActive(res.data.is_active))
      .catch(err => console.error(err));
  }, []);

  // ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ† ๊ธ€ ์š”์ฒญ / Request toggle when button is clicked
  // Request toggle when button is clicked
  const handleToggle = async () => {
    try {
      const nextState = !isActive;
      const res = await axios.post('http://localhost:3000/toggle', { isActive: nextState });
      setIsActive(res.data.is_active);
    } catch (err) {
      alert("์„œ๋ฒ„ ์—ฐ๊ฒฐ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค./Failed to connect to server.");
    }
  };

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        justifyContent: "center", // ์„ธ๋กœ ์ค‘์•™ ์ •๋ ฌ / Vertical center alignment
        alignItems: "center", // ๊ฐ€๋กœ ์ค‘์•™ ์ •๋ ฌ / horizontal center alignment
        height: "100vh", // ํ™”๋ฉด ์ „์ฒด ๋†’์ด ์‚ฌ์šฉ / Use full screen height
        width: "100vw", // ํ™”๋ฉด ์ „์ฒด ๋„ˆ๋น„ ์‚ฌ์šฉ / Use full screen width
        margin: 0, // ๊ธฐ๋ณธ ์—ฌ๋ฐฑ ์ œ๊ฑฐ / Remove default margins
      }}
    >
      <div style={{ textAlign: "center", marginTop: "50px" }}>
        <h2>
          ํ˜„์žฌ ์ƒํƒœ/Current Status:{" "}
          {isActive ? "๐Ÿ”ต ํ™œ์„ฑ/Active" : "๐Ÿ”ด ๋น„ํ™œ์„ฑ/inActive"}
        </h2>
        <button
          onClick={handleToggle}
          style={{
            padding: "10px 20px",
            fontSize: "16px",
            backgroundColor: isActive ? "#4CAF50" : "#f44336",
            color: "white",
            border: "none",
            borderRadius: "5px",
            cursor: "pointer",
          }}
        >
          {isActive ? "๋น„ํ™œ์„ฑํ™”ํ•˜๊ธฐ/InActivate" : "ํ™œ์„ฑํ™”ํ•˜๊ธฐ/Activate"}
        </button>
      </div>
    </div>
  );
}

export default App;

๐Ÿ‘‰๐Ÿป ์Šคํฌ๋ฆฐ ์ƒท / ScreenShot

โœ”๏ธ InActive

โœ”๏ธ Active

โœ”๏ธ postgresql

Leave a Reply