728x90

React 에서 RSA 암호화를 하여 패스워드를 Back-End(PHP)로 전송하고, PHP에서 복호화 처리를 해봤다.

npm install jsencrypt@3.2.1

로 모듈을 추가하고 아래와 같이 코드를 전송하면 된다.

jsencrypt 버전은 3.2.1 에서 정상동작함을 확인했다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
import { JSEncrypt } from "jsencrypt"// npm install jsencrypt
 
const Login = () => {
    // PHP 를 이용하여 Web에서 생성한 공개키 : 실제 길이는 훨씬 더 길다.
    const publicKey = `MIGfMA0GCSqGSIb3DQEBED/dKAJT7vdgzXooBzzTyUHwVJGyA1mKYDCIyU5/IQIDAQAB`;
    const encrypt = new JSEncrypt(); // Start our encryptor.
    encrypt.setPublicKey(publicKey); // Assign our encryptor to utilize the public key.
 
    const navigate = useNavigate();
    const initData = {
        userID: '',
        password: ''
    }
 
    const [formData, setFormData] = useState(initData);
    const [users, setUsers] = useState([]);
    // 첫번째 원소 : 현재 상태, 두번재 원소 : 상태를 바꾸어 주는 함수
    const [error, setError] = useState(null);
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        // e.target.name 은 해당 input의 name을 가리킨다.
        //console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const params = {
            userID: formData.userID,
            password: encrypt.encrypt(formData.password)
        }
        console.log(params);
        axios.post('/reactSample/loginChk.php', params)
            .then((res) => {
                console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    setUsers(res.data.userinfo);
                    navigate('/');
                } else {
                    console.log(res.data.message);
                    setError(true);
                }
            })
            .catch(error => {
                console.log(error.response)
            });
    }
 
    return (
        <div className="container h-100 mt-5">
            <div className="row d-flex justify-content-center align-items-center h-100">
                <div className="col-12 col-md-9 col-lg-7 col-xl-6">
                    <div className="card">
                        <div className="card-body p-5">
                            <h2 className="text-uppercase text-center mb-5">Sign In</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userID">userID</label>
                                    <input type="text" name="userID" onChange={onChangeInput} id="userID"
                                           className="form-control form-control-lg" value={formData.userID}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="password">Password</label>
                                    <input type="password" name="password" onChange={onChangeInput} id="password"
                                           className="form-control form-control-lg" value={formData.password}
                                           required/>
                                </div>
 
                                { error &&
                                <div className="alert alert-danger" role="alert">
                                    로그인 정보를 확인하세요!
                                </div>
                                }
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-primary btn-block btn-lg gradient-custom-3 text-body">로그인
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/register" className="fw-bold text-body"><u>회원가입</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Login;
cs

 

 

PHP 에서 RSA 공개키 얻는 방법

 
<?php
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: application/json; charset=UTF-8");
 
$pubkey = get_publickey();
echo $pubkey;
 
function get_publickey() {
    // 경로 : 절대경로로 설정 필요
    $rsakeyfile = '/home/rsa/key/rsa_pub.pem';
    
    $fp = fopen($rsakeyfile,"r");
    $key = "";
    while(!feof($fp)) {
        $key .= fgets($fp,4096);
    } 
    fclose($fp);
 
    $key = preg_replace('/\r\n|\r|\n/','',$key);
    $key = str_replace('-----BEGIN PUBLIC KEY-----','',$key);
    $key = str_replace('-----END PUBLIC KEY-----','',$key);
    return $key;
 
/*
CentOS 리눅스 에서 RSA 공개키, 개인키 생성 방법
mkdir -p /home/rsa/key/
cd /home/rsa/key/
 
# Private Key 생성
openssl genrsa -out rsa_pri.pem 1024
 
# Public Key 생성
openssl rsa -pubout -in rsa_pri.pem -out rsa_pub.pem
 
*/
?>

 

 

PHP loginChk.php

- RSA 복호화 처리 함수는 LoginClass.php 파일에 포함되어 있다.

<?php
// 파일을 직접 실행하는 비정상적 동작을 방지 하기 위한 목적
if(isset($_POST&& $_SERVER['REQUEST_METHOD'== "POST"){
    $_POST = json_decode(file_get_contents("php://input"),true); 
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID&& !empty($userID&& isset($password&& !empty($password)) {
        require_once 'phpclass/config.php';
        require_once 'phpclass/dbconnect.php';
        require_once 'phpclass/loginClass.php';
        $c = new LoginClass();
 
        header("Cache-Control: no-cache, must-revalidate");
        header("Content-type: application/json; charset=UTF-8");
 
        $password = $c->rsa_decrypt($password);
 
        $user = $c->getUser($userID$password);
        if($user['idx'== 1){ // 로그인 정보가 일치하면
            $_SESSION['userID'= $user['userID'];
            $_SESSION['userNM'= $user['userNM'];
            $_SESSION['admin'= $user['admin'];
 
            $row = array("userNM"=>$user['userNM'],"mobileNO"=>$user['mobileNO'],"profileImg"=>$user['idx']);
 
            $status = "success";
            $message = "";
            $userinfo = $row;
        } else {
            $status = "로그인 에러";
            $message = "다시 한번 시도하시기 바랍니다.";
            $userinfo = null;
        }
 
        $result = array(
            'status' => $status,
            'message' => $message,
            'userinfo' => $userinfo
        );
        echo json_encode($result);
 
    }
else { // 비정상적인 접속인 경우
    echo 0// loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>
 

 

 

 

728x90

'React > React-PHP' 카테고리의 다른 글

React + PHP Login 처리  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
728x90

React 에서 로그인 처리하는 걸 테스트하고 적어둔다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
 
const Login = () => {
    const navigate = useNavigate();
    const initData = {
        status: '',
        message: '',
        userinfo: {
            userNM: '',
            mobileNO: '',
            profileImg: ''
        }
    }
 
    const [formData, setFormData] = useState(initData);
    const [users, setUsers] = useState([]);
    // 첫번째 원소 : 현재 상태, 두번재 원소 : 상태를 바꾸어 주는 함수
    const [error, setError] = useState(null);
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        // e.target.name 은 해당 input의 name을 가리킨다.
        //console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const params = {
            userID: formData.userID,
            password: formData.password
        }
        console.log(params);
        axios.post('/reactSample/loginChk.php', params)
            .then((res) => {
                console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    setUsers(res.data.userinfo);
                    navigate('/');
                } else {
                    console.log(res.data.message);
                    setError(true);
                }
            })
            .catch(error => {
                console.log(error.response)
            });
    }
 
    return (
        <div className="container h-100 mt-5">
            <div className="row d-flex justify-content-center align-items-center h-100">
                <div className="col-12 col-md-9 col-lg-7 col-xl-6">
                    <div className="card">
                        <div className="card-body p-5">
                            <h2 className="text-uppercase text-center mb-5">Sign In</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userID">userID</label>
                                    <input type="text" name="userID" onChange={onChangeInput} id="userID"
                                           className="form-control form-control-lg" value={formData.userID}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="password">Password</label>
                                    <input type="password" name="password" onChange={onChangeInput} id="password"
                                           className="form-control form-control-lg" value={formData.password}
                                           required/>
                                </div>
 
                                { error &&
                                <div className="alert alert-danger" role="alert">
                                    로그인 정보를 확인하세요!
                                </div>
                                }
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-primary btn-block btn-lg gradient-custom-3 text-body">로그인
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/register" className="fw-bold text-body"><u>회원가입</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Login;

간혹 보면 "아이디가 존재하지 않는다", "비밀번호가 틀렸다" 라는 문구를 출력하는 경우가 있는데 이런 경우 해커에게 빌미를 제공하는 것이다. 아이디가 있건 없건, 비밀번호가 틀렸든 간에 "로그인 정보가 일치하지 않는다"는 문구 하나로 처리해야 안전하다. (모의 해킹 시 지적사항)

 

Login.js
0.00MB

 

 

아직 전역 상태관리 처리까지는 못해봤다.

전역 상태관리 기준으로 테스트하게되면 업데이트할 예정이다.

 

PHP 로그인 처리 코드

- PHP 코드 결과로 만들어진 JSON 구조를 토대로 useState 초기값 구조를 작성한다.

<?php
// 파일을 직접 실행하는 비정상적 동작을 방지 하기 위한 목적
if(isset($_POST&& $_SERVER['REQUEST_METHOD'== "POST"){
    $_POST = json_decode(file_get_contents("php://input"),true); 
    @extract($_POST); // $_POST['loginID'] 라고 쓰지 않고, $loginID 라고 써도 인식되게 함
    if(isset($userID&& !empty($userID&& isset($password&& !empty($password)) {
        require_once 'phpclass/dbconnect.php';
        require_once 'phpclass/loginClass.php';
        $c = new LoginClass();
 
        header("Cache-Control: no-cache, must-revalidate");
        header("Content-type: application/json; charset=UTF-8");
 
        $user = $c->getUser($userID$password);
        if($user['idx'== 1){ // 로그인 정보가 일치하면
            $_SESSION['userID'= $user['userID'];
            $_SESSION['userNM'= $user['userNM'];
            $_SESSION['admin'= $user['admin'];
 
            $row = array("userNM"=>$user['userNM'],"mobileNO"=>$user['mobileNO'],"profileImg"=>$user['idx']);
 
            $status = "success";
            $message = "";
            $userinfo = $row;
        } else {
            $status = "로그인 에러";
            $message = "다시 한번 시도하시기 바랍니다.";
            $userinfo = null;
        }
 
        $result = array(
            'status' => $status,
            'message' => $message,
            'userinfo' => $userinfo
        );
        echo json_encode($result);
    }
else { // 비정상적인 접속인 경우
    echo 0// loginChk.php 파일을 직접 실행할 경우에는 화면에 0을 찍어준다.
    exit;
}
?>
 

 

 

 

728x90

'React > React-PHP' 카테고리의 다른 글

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
728x90

json 데이터 구조

{
  "result": [
    {
      "idx"1,
      "userNM""개발자",
      "mobileNO""01000010001",
      "telNO""0234560001",
      "photo""1.jpg"
    },
    {
      "idx"2,
      "userNM""이정은",
      "mobileNO""01001230001",
      "telNO""",
      "photo""2.jpg"
    },
    {
      "idx"3,
      "userNM""김홍길",
      "mobileNO""01001230002",
      "telNO""",
      "photo"""
    },
    {
      "idx"4,
      "userNM""최신형",
      "mobileNO""01001230003",
      "telNO""",
      "photo""4.jpg"
    },
  ]
}

 

React useEffect 함수

const initData = {
    result: {
        idx: 0,
        userNM: '',
        mobileNO: '',
        telNO: '',
        photo: ''
   }
}
const [arrayData, setArrayData] = useState(initData);
 
useEffect( () => {
    const params = {
        idx: 1
    }
    axios.post('http://localhost/reactSample/getContact.php', params)
        .then(res => {
            //console.log(res);
            if (res.status === 200) {
                // console.log(res.data.result);
                setArrayData(res.data.result);
            }
        })
        .catch(error => {
            console.log(error.response)
        });
}, []);
 

구글링을 하면 axios post 방식으로 params 를 넘기는 방식이 다양하게 나오는데 테스트를 해보니 안되더라.

위와 같이 하면 된다.

PHP 에서는 변수를 $data['idx'] 로 인식되더라.

유투브 강의 자료 따라서 할 때 변수를 잘못 인식할 수도 있으니 반드시 테스트가 필요하다.

 

 

npm install 및 import

//npm install --save axios
 
import {useEffect, useState} from "react";
import axios from "axios";

 

 

실전형 REST API 예제

- React 에서 전달받은 데이터를 처리하는 PHP 파일

<?php
//header("Access-Control-Allow-Origin: http://localhost:3000");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 3600");
//header("Access-Control-Allow-Headers: Content-Type, Authorization");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
 
$data = json_decode(file_get_contents("php://input"),true);
 
require_once 'phpclass/config.php';
require_once 'phpclass/dbconnect.php';
require_once 'phpclass/loginClass.php';
$c = new LoginClass();
 
//키워드 확인
if(!isset($data['keyword']) || empty($data['keyword'])){
    $result = array(
        'status' => "fail",
        'message' => "no keyword",
        'addrinfo' => null
    );
    echo json_encode($result);
    exit;
}
 
$keyword=$data['keyword'];
//키워드 일치 확인
if(strcmp($keyword,$mykey)<>0){
    $result = array(
        'status' => "keyfail",
        'message' => "서버와 단말의 KEY가 일치하지 않습니다.",
        'addrinfo' => null
    );
    echo json_encode($result);
    exit;
}
 
 
$column ="idx,userNM,mobileNO,telNO,photo";
$sql = "select idx,userNM,mobileNO,telNO,photo from Person";
if(!empty($search)) {
    $where = "userNM LIKE '%".$search."%' or mobileNO LIKE '%".$search."%'";
else {
    $where = "";
}
 
if(strlen($where> 0){
    $sql .= " where ".$where;
}
 
$R = array(); // 결과 담을 변수 생성
$result = $c->putDbArray($sql);
while($row = $result->fetch_assoc()) {
    $path = "./photos/".$row['photo'];
    if(!file_exists($path)) {
        $row['photo'= "";
    } else {
        $row['photo'];
    }
    array_push($R$row);
}
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: application/json; charset=UTF-8");
 
$status = "success";
$message = "";
$addrinfo = $R// 전체 ArrayList 데이터
 
$result = array(
    'status' => $status,
    'message' => $message,
    'addrinfo' => $addrinfo
);
echo json_encode($result);//배열-문자열등을 json형식의 '문자열'로 변환
?>
 
cs

 

위와 같은 JSON 데이터를 처리하기 위한 React POST 전송 코드 구현 사항

import {useEffect, useState} from "react";
import axios from "axios";
import moment from 'moment';
import * as config from './config';
 
const ListData = () => {
    const today = moment().format('YYYYMMDD');
    const initData = {
        status:'',
        message:'',
        addrinfo: {
            idx: 0,
            userNM: '',
            mobileNO: '',
            telNO: '',
            photo: ''
       }
    }
    const [arrayData, setArrayData] = useState(initData);
 
    useEffect( () => {
        const params = {
            keyword: config.URLKEY + today,
        }
        axios.post('http://localhost/reactSample/getContact.php', params)
            .then(res => {
                //console.log(res);
                if (res.status === 200 && res.data.status === 'success') {
                    console.log(res.data.addrinfo);
                    setArrayData(res.data.addrinfo);
                } else {
                    console.log(res.data.message);
                }
            })
            .catch(error => {
                console.log(error.response)
            });
    }, []);
 
    // 화면 UI 구성은 생략
    return (
        <div className="container h-100 mt-5">
        </div>
    )
}
 
export default ListData;

 

모듈 설치 사항

npm install --save axios
npm install moment --save

 

 

주의사항

Android APP 과 PHP 간에 주고받은 PHP 파일 형식과 React 대응 PHP 파일 형식이 다르다.

Android/jQuery POST 변수 인식 방법은

if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){

}

로 하면 GET 방식으로 실행하면 내용을 확인할 수가 없다.

그런데 React 대응 PHP 코드는 GET 방식으로도 실행이 된다.

그러므로 keyword 또는 session 처리를 잘 구현해서 PHP 코드를 작성해야 할 것 같다.

 

ListData.js
0.00MB

728x90

'React > React-PHP' 카테고리의 다른 글

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React + PHP Login 처리  (0) 2022.08.27
React - PHP 간 연동 입문기  (0) 2022.08.20
블로그 이미지

Link2Me

,
728x90

https://react-bootstrap.github.io/getting-started/introduction/

 

React-Bootstrap

The most popular front-end framework, rebuilt for React.

react-bootstrap.github.io

에 설명된 것처럼

npm install react-bootstrap bootstrap

으로 모듈을 추가하고, App.js 또는 index.js 에

import 'bootstrap/dist/css/bootstrap.min.css';

를 추가한다.

 

Header.js 파일을 아래와 같이 하고 테스를 했더니 PC화면 사이즈에서는 속도 문제는 없다.

Navbar.Offcanvas 기능이 활성화되는 스마트폰 크기로 되었을 때 Menu 반응속도가 너무 느리다.

import Button from 'react-bootstrap/Button';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
import NavDropdown from 'react-bootstrap/NavDropdown';
import Offcanvas from 'react-bootstrap/Offcanvas';
 
const Header = () => {
    return (
        <>
            <Navbar bg="primary" expand='sm' className="mb-3">
                <Container fluid>
                    <Navbar.Brand href="/">Navbar</Navbar.Brand>
                    <Navbar.Toggle aria-controls='navbar-expand-sm'/>
                    <Navbar.Offcanvas id='navbar-expand-sm' aria-labelledby='navbar-expand-sm' placement="end">
                        <Offcanvas.Header closeButton>
                            <Offcanvas.Title id='navbarLabel-expand-sm'>
                                홍길동
                            </Offcanvas.Title>
                        </Offcanvas.Header>
                        <Offcanvas.Body>
                            <Nav className="justify-content-end flex-grow-1 pe-3">
                                <Nav.Link href="/">Home</Nav.Link>
                                <Nav.Link href="/login">Login</Nav.Link>
                                <Nav.Link href="/register">Sign Up</Nav.Link>
                                <NavDropdown title="Dropdown" id='navbarDropdown-expand-sm'>
                                    <NavDropdown.Item href="/login">로그인</NavDropdown.Item>
                                    <NavDropdown.Item href="/register">회원가입</NavDropdown.Item>
                                    <NavDropdown.Divider/>
                                    <NavDropdown.Item href="#action5">
                                        Something else here
                                    </NavDropdown.Item>
                                </NavDropdown>
                            </Nav>
                        </Offcanvas.Body>
                    </Navbar.Offcanvas>
                </Container>
            </Navbar>
        </>
    )
}
 
export default Header;

 

Navbar.Offcanva 기능이 없는 단순 형태 구성 코드는 속도 문제 없었다.

import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
 
const Header = () => {
    return (
        <>
            <Navbar bg="primary" variant="dark">
                <Container fluid>
                    <Navbar.Brand href="/">Navbar</Navbar.Brand>
                    <Navbar.Toggle aria-controls="responsive-navbar-nav"/>
                    <Navbar.Collapse id="responsive-navbar-nav">
                        <Nav className="me-auto">
                            <Nav.Link href="/">Home</Nav.Link>
                            <Nav.Link href="/register">Register</Nav.Link>
                            <Nav.Link href="/login">Login</Nav.Link>
                        </Nav>
                    </Navbar.Collapse>
                </Container>
            </Navbar>
        </>
    )
}
 
export default Header;

Layout 구성하는 것에 대해서 좀 더 다양한 테스트를 해봐야 알 수 있을 듯 싶다.

 

728x90

'React > React' 카테고리의 다른 글

React useRef 사용 예제  (0) 2022.10.15
React useReducer  (0) 2022.10.13
React CORS error 해결 방법  (0) 2022.08.20
React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
블로그 이미지

Link2Me

,
728x90

React 가 대세라서 React 학습을 해보는 중이다.

인프런 사이트 강좌도 들어보고 fastcampus 강좌도 들어보고 있다. 사이트마다 장단점이 있는 거 같다.

전체적인 개념을 잡으면서 하는 것은 fastcampus 강좌가 좋은데, 최근에 변경된 것을 반영하지 않은 것이 있다보니 따라하기 실습을 해보면 잘 동작되지 않아서 진도 나기가기 쉽지 않아 중도에 멈춤 상태이다.

React 동영상 강좌를 가급적이면 2022년에 나온 걸 중심으로 학습하는게 정신 건강에 좋은 듯 싶다.

 

Back-End는 지금까지 배워왔던 PHP 로 해보는게 좋을 듯 싶어서 유투브 동영상 강좌를 검색하니 인도 개발자가 올린 동영상 강좌가 괜찮은 거 같아서 따라서 해보기로 하고 어제 동영상을 멈춰가면서 따라하기를 해보았다. 아쉽게도 소스코드를 Github 에 공개하지 않아서 일일이 타이핑을 하는 수고를 해야 한다.

https://www.youtube.com/watch?v=nmCeSPGcBnY 

 

프로젝트 생성 : npx create-react-app react-php

프로젝트로 이동 : cd react-php

 

모듈 추가

npm install --save bootstrap
npm install --save react-router-dom@6
npm install --save axios

 

동영상 강좌에서 bootsrap 모듈을 추가하라고 나오는 건 없다. 아직 bootstrap 모듈 추가한 것에 대한 기능을 제대로 사용할 줄 모른다. 나중에 사용법을 익힐 것을 감안하고 모듈 추가를 해두었다.

 

구글에서 boostrap cdn 을 입력하고 css 버튼을 눌러 하단의 HTML 코드를 복사하여 public 폴더 index.html 파일 헤더 부분에 붙여넣기 한다.

 

App.js

회원 가입과 로그인 기능을 보여주는 메인화면 구성을 하기 위한 App.js 파일 구성이다.

import "bootstrap/dist/css/bootstrap.min.css"
import './App.css';
import Header from "./Header";
import {BrowserRouter, Routes, Route} from "react-router-dom";
import Home from "./Home";
import Login from "./Login";
import Register from "./Register";
 
function App() {
    return (
        <BrowserRouter>
            <div className="container">
                <Header/>
                <Routes>
                    <Route path="/" element={<Home/>}/>
                    <Route path="/login" element={<Login/>}/>
                    <Route path="/register" element={<Register/>}/>
                </Routes>
            </div>
        </BrowserRouter>
    );
}
 
export default App;

 

Header.js

header.js 구성을 위해서 구글에서 bootstrap navbar 검색하고 Navbar text with an inline element 복사하여
Header.js 에 붙여넣기 한다. Webstorm에서 class 는 자동으로 className 으로 변경해 주더라.

동영상 보면 Visual Studio Code(vscode)에서 class 자동 변경은 안되는거 같더라.

import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
const Header = () => {
    return (
        <nav className="navbar navbar-expand-lg bg-light">
            <div className="container-fluid">
                <a className="navbar-brand" href="#">Navbar w/ text</a>
                <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
                        aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
                <div className="collapse navbar-collapse" id="navbarText">
                    <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                        <li className="nav-item">
                            {/*<a className="nav-link active" aria-current="page" href="#">Home</a>*/}
                            <Link to="/" className="nav-link active">Home</Link>
                        </li>
                        <li className="nav-item">
                            <Link to="/register" className="nav-link">Register</Link>
                        </li>
                        <li className="nav-item">
                            <Link to="/login" className="nav-link">Login</Link>
                        </li>
                    </ul>
                    <span className="navbar-text">
                    </span>
                </div>
            </div>
        </nav>
    )
}
 
export default Header;

 

 

<a className="nav-link active" aria-current="page" href="#">Home</a>

부분을

<Link to="/" className="nav-link active">Home</Link>

로 변경하면 된다.

 

이 코드로 테스트를 해보니 PC화면에서는 버튼 기능이 잘 동작되는데 모바일 크기 사이즈로 화면을 축소하면 메뉴 선택하는 부분이 동작되지 않는 현상이 있다.

단순하게 bootstrap 5 코드를 React 로 변경만 했기 때문에 생기는 문제점으로 Navbar 가 제대로 동작되지 않는 듯 하다.

이 부분은 bootstrap 모듈 추가한 방식으로 다시 한번 테스트를 해볼 예정이다.

지금은 React - PHP 간 연동 처리하는 부분이 중점이라 그 부분에 치중하고 글을 작성해두는 것이다.

 

 

Home.js

const Home = () => {
    return (
        <div>
            Welcome to Home page
        </div>
    )
}
export default Home;

이 코드는 형태만 보여주는 수준이다.

Login.js 파일도 이와 같은 형태라서 보여주는 건 생략한다.

 

Register.js

구글에서 bootstrap form 으로 검색하면 https://mdbootstrap.com/docs/standard/forms/overview/ 가 검색된다.

여기서 적당한 것을 복사하여 붙여넣기를 하고 불필요한 부분은 수정한다.

제공된 기본 Form 에서 name, 상태변화값 onChangeInput, value 를 추가하고 id 값도 알기 쉽게 변경한다.

아래와 같이 코드를 작성하면 React 버전 회원가입 기본 폼이 완성된다.

PHP 로 submit 결과를 전송하기 위해서 axio.post 로 전달하고 결과를 돌려받도록 코드를 작성한다.

이 부분이 jQuery ajax 로 전송하는 것과 좀 다르다.

import {useState} from "react";
import {Link, useNavigate} from "react-router-dom";
import axios from "axios";
 
const Register = () => {
    const navigate = useNavigate();
    const [formData, setFormData] = useState({
        userNM: "",
        email: "",
        password: ""
    })
 
    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value
        });
        console.log(formData);
    }
 
    const submitForm = (e) => {
        e.preventDefault();
        const sendData = {
            userNM: formData.userNM,
            email: formData.email,
            password: formData.password
        }
        console.log(sendData);
        axios.post('http://localhost/php-react/insert.php', sendData)
            .then((res) => {
                console.log(res.data);
                navigate('/login');
            })
            .catch(error => {
                console.log(error.response)
            });
    }
 
    return (
        <div className="container h-100 mt-5">
            <div className="row d-flex justify-content-center align-items-center h-100">
                <div className="col-12 col-md-9 col-lg-7 col-xl-6">
                    <div className="card">
                        <div className="card-body p-5">
                            <h2 className="text-uppercase text-center mb-5">Create an account</h2>
                            <form onSubmit={submitForm}>
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="userNM">Your Name</label>
                                    <input type="text" name="userNM" onChange={onChangeInput} id="userNM"
                                           className="form-control form-control-lg" value={formData.userNM}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="email">Your Email</label>
                                    <input type="email" name="email" onChange={onChangeInput} id="email"
                                           className="form-control form-control-lg" value={formData.email}
                                           required/>
                                </div>
 
                                <div className="form-outline mb-4">
                                    <label className="form-label" htmlFor="password">Password</label>
                                    <input type="password" name="password" onChange={onChangeInput} id="password"
                                           className="form-control form-control-lg" value={formData.password}
                                           required/>
                                </div>
 
                                <div className="d-flex justify-content-center">
                                    <button type="submit"
                                            className="btn btn-success btn-block btn-lg gradient-custom-4 text-body">Register
                                    </button>
                                </div>
 
                                <p className="text-center text-muted mt-5 mb-0">
                                    <Link to="/login" className="fw-bold text-body"><u>로그인</u></Link>
                                </p>
 
                            </form>
 
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}
 
export default Register;

 

PHP DB 연결 코드 dbconnect.php

이 부분은 Legacy PHP 로 DB를 연결하는 방법이며, 내가 즐겨 사용하는 방식 중 하나다.

<?php
$db['server'= 'localhost';
$db['dbname'= 'studydb';
$db['user_name'= 'reactfox';
$db['password'= 'Wonderfull!';
$db['port'= "3306";
 
$db = isConnectDb($db);
 
function isConnectDb($db)
{
    $conn = mysqli_connect($db['server'],$db['user_name'],$db['password'],$db['dbname'],$db['port']);
    mysqli_set_charset($conn"utf8");  // DB설정이 잘못되어 euc-kr 로 되어 있으면 문제가 됨
    if (mysqli_connect_errno()) {
        echo "Failed to connect to MySQL: " . mysqli_connect_error();
        exit;
    } else {
        return $conn;
    }
}
 
/* 사용자 권한 등록
create database studydb default character set utf8;
 
use mysql;
create user reactfox@localhost identified by 'Wonderfull!';
grant all privileges on studydb.* to reactfox@localhost;
flush privileges;
quit
*/
?>
 
 

 

DB를 연결하기 위해 studydb 를 생성하고 DB 접속 권한을 부여하기 위한 걸 해준다.

이제 사용자 정보를 저장하기 위한 초간단 테이블을 구성한다. 이 테이블은 연동 과정을 보여주기 위한 것이지 실제 사용 수준의 테이블 스키마는 아니다.

CREATE TABLE `users` (
  `id` int(11NOT NULL,
  `name` varchar(50CHARACTER SET utf8mb3 NOT NULL,
  `email` varchar(50CHARACTER SET utf8mb3 NOT NULL,
  `password` varchar(200CHARACTER SET utf8mb3 NOT NULL
ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `email` (`email`);
 
ALTER TABLE `users`
  MODIFY `id` int(11NOT NULL AUTO_INCREMENTAUTO_INCREMENT=1;
COMMIT;

email 칼럼은 UNIQUE KEY 를 지정하여 중복 저장되지 않도록 했다.

 

 

insert.php

아래 코드 상단에 처리하는 기능에 대해서는 다 모른다. 이 부분에서 엄청난 삽질을 하면서 개고생을 좀 했다.

Access-Control-Allow-Headers : 가 된 것이 문제가 되는 줄 몰랐다.

Access-Control-Allow-Headers: 와 같이 공백이 있으면 절대 안되더라. ㅠㅠㅠ

이것 때문에 CORS 에러 메시지 숱하게 보이고 구글링 하면서 별의 별 것을 다 찾아보게 되었다.

덕분에 이 코드의 중요성에 대해서 알게 된 것 정도이다.

윈도우에서 localhost 로 PHP 도 설치하고, React 도 설치해서 동작시키는 것에서는 CORS 에러를 만날 일이 적은 듯 하다. 리눅스 버전을 설치하고 나서 Same IP, Different Port 로 크롬브라우저가 CORS 에러 메시지를 보여주는 걸 해결하기 위해 수많은 삽질 끝에(?) 해결을 하긴 했다. 테스트 해보니 더 코드를 정교하게 할 부분도 있기는 있는 듯 하다.

https://link2me.tistory.com/2228 에 CORS 에러 해결 방법이 있으니 참조하면 된다.

<?php
//header("Access-Control-Allow-Origin: http://localhost:3000");
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: access");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Max-Age: 3600");
//header("Access-Control-Allow-Headers: Content-Type, Authorization");
//header("Access-Control-Allow-Headers: Origin, Accept, X-Requested-With, Content-Type, Access-Control-Allow-Headers, Authorization");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
 
$data = json_decode(file_get_contents("php://input"));
 
if(isset($data&& !empty($data)){
 
    require_once 'dbconnect.php';
 
    $name = $data->userNM;
    $email = $data->email;
    $password = $data->password;
    $sql = "INSERT INTO users (name,email,password) VALUES ('$name','$email','$password')";
    if(mysqli_query($db,$sql)){
        echo json_encode(["status" => "success""message" => "User Inserted"'response' => 200]);
    } else {
        echo json_encode(["status" => "fail""message" => "Unable to register the user!"'response' => 400]);
    }
}
?>

 

UI 구성 처리에 대한 사항은 bootstrap 모듈 연동 방법으로 다시 한번 테스트 해볼 생각이다.

샘플로서의 가치가 있을 수준이 되면 my github 에 올려두고 링크를 걸어둘 것이다.

이상으로 인도 개발자 유투브 동영상 참조 및  다른 코드를 찾아 수정하면서 React-PHP 연동에 성공했다는 뿌듯함에 적어뒀다.

 

최근에 알게된 코딩앙마님의 React 강좌가 좋은 듯하여 학습 중이다.

https://www.youtube.com/watch?v=05uFo_-SGXU&list=PLZKTXPmaJk8J_fHAzPLH8CJ_HO_M33e7- 

 

728x90

'React > React-PHP' 카테고리의 다른 글

RSA Encryption Login in React.js and PHP  (0) 2022.08.27
React + PHP Login 처리  (0) 2022.08.27
React useEffect example (php REST API)  (0) 2022.08.22
블로그 이미지

Link2Me

,
728x90

React (Front-End) 와 PHP (Back-End) 간에 통신하는 기능으로 유투브 동영상을 시청하면서 타이밍해가면서 동작 여부를 확인하는데 안된다.

 

윈도우에서 React 를 설치하고, 윈도우에 AutoSet10 을 설치하고 http://localhost/php-react/insert.php 로 데이터 전송을 시도하면 같은 localhost 로 인식하여 MySQL DB에 데이터가 잘 저장된다.

 

윈도우에 CentOS 7.9 를 VirtualBox 를 이용하여 설치하고, Node.js 와 React 를 설치하고 PHP 도 같이 설치했다.

IPTIME 공유기 환경에서 http://192.168.1.20:3000 번으로 react 개발자 모드로 접속하고,

http://192.168.1.20/php-react/insert.php 로 접속을 했더니 에러가 발생한다.

 

80 포트와 3000번 포트가 서로 달라서 생기는 문제다.

일반적으로 브라우저는 보안 문제로 인해 동일 출처 정책(SOP, Same Origin Policy)을 따른다.

URL의 프로토콜, 호스트, 포트가 모두 같아야 동일한 출처로 볼 수 있는데, 예를 들어 abc.com 호스트에게 받은 페이지에서 cde.com 호스트로 데이터를 요청할 수 없다. 출처가 다른 호스트로 데이터를 요청하는 경우 CORS 정책을 위반하게 된다. 

 

Register.js 파일 내용

 

insert.php 파일 내용

 

문제 해결 방법

1. package.json  파일에 추가할 사항

 

2. Register.js 파일 수정사항

http://192.168.1.20 remove

3. Chrome Broswer 결과 확인

4. DB 테이블 확인

테이블에 저장이 잘 된 것을 확인할 수 있다.

 

 

 

 

 

 

728x90

'React > React' 카테고리의 다른 글

React useReducer  (0) 2022.10.13
React-bootstrap Header.js 테스트  (0) 2022.08.21
React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
React useState  (0) 2022.06.04
블로그 이미지

Link2Me

,
728x90

객체는 프로퍼티와 메소드의 집합이다.

객체 리터럴을 사용해서 객체를 생성하는 것은 연속된 구조체나 연관된 데이터를 일정한 방법으로 변환하고자 할 때  많이 쓰이는 방법이다.

this 키워드는 지금 동작하고 있는 코드를 가지고 있는 객체를 가리킨다. 아래 예제에서 this 는 user 객체와 동일하다. 

 

// Object(객체 데이터) : 여러 데이터를 key:value 형태로 저장한다. {}
let user = {
    name : 'Json',
    nickname : 'Link2Me',
    age : 25,
    getName: function () { // 메소드(Method)
        console.log(`이름:${this.name}, 별명:${this.nickname}, 나이:${this.age}`)
    }
};
 
console.log(user.name);
console.log(user.nickname);
console.log(user.age);
user.getName();

 

 

728x90

'React > morden javascript' 카테고리의 다른 글

[Javascript] _cloneDeep()  (0) 2022.10.05
[ES6] Spread 연산자  (0) 2022.10.02
자바스크립트 호이스팅(Hoisting)  (0) 2022.06.10
Javascript this and Class  (0) 2022.06.09
javascript 콜백 함수(callback function)  (0) 2022.05.27
블로그 이미지

Link2Me

,
728x90

변수의 선언을 해당 스코프의 맨 위로 끌어올려졌다. → 호이스팅

console.log(x);
var x = 1;
 
// 위 코드는 아래와 똑같다.
var x;
console.log(x);
= 1;

 

자바스크립트 Hoisting 이란 함수 선언부가 유효범위 최상단으로 끌어올려지는 현상을 말한다.

함수를 하단에 작성하는 것이 좋다.

 

const a = 5;
 
double();
 
function double(){
  console.log(a*2);
}

 

 

타이머 함수

setTimeout(함수, 시간); // 일정시간 후 함수 실행

clearTimeout(); // 설정된 Timeout 함수를 종료

 

setInterval(함수, 시간); // 시간 간격마다 함수 실행

clearInterval();  // 설정된 Interval 함수를 종료

 

 

const timer = setTimeout(()=> {
  console.log('Hello world');
},2000);
 
const h1El = document.querySelector('h1');
h1El.addEventListener('click', ()=> {
  clearTimeout(timer);
});

 

728x90

'React > morden javascript' 카테고리의 다른 글

[ES6] Spread 연산자  (0) 2022.10.02
자바스크립트 Object  (0) 2022.06.11
Javascript this and Class  (0) 2022.06.09
javascript 콜백 함수(callback function)  (0) 2022.05.27
javascript 화살표 함수(람다식)  (0) 2022.05.27
블로그 이미지

Link2Me

,
728x90

this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-reference variable)이다.

세부적인 사항은 https://velog.io/@realryankim/JavaScript-this%EB%9E%80 를 참조하면 도움된다.

 

// this
// 일반(normal) 함수는 호출 위치에 따라 this 정의
// 화살표(Arrow) 함수는 자신의 선언된 함수 범위에서 this 정의
 
const link2me = {
    name : 'Link2Me',
    normal: function () {
        console.log(this.name);
    },
    arrow: () => {
        console.log(this.name);
    }
}
 
link2me.normal(); // 결과 : Link2Me
link2me.arrow();  // 결과 : undefined
 
function User(name) {
    this.name = name;
}
 
User.prototype.normal = function () {
    console.log(this.name);
}
 
User.prototype.arrow = () => {
    console.log(this.name);
}
 
const link2u = new User('Link2U');
link2u.normal(); // 결과 : Link2U
link2u.arrow(); // 결과 : undefined

 

ES6 Class

- 자바스크립트에서 클래스는 프로토타입을 이용해서 만들어졌지만 ES5의 클래스 의미와는 다른 문법과 의미를 가진다.

- 자바스크립트에서 클래스 사용은 ES6에서부터 지원을 하기 시작했다. ES5까지 자바스크립트에는 클래스가 없었다.
  익스플로러에서는 해당 코드 사용이 불가능하나, 최신 브라우저를 이용할 경우 class를 지원한다.

  생김새만 클래스 구조이지, 엔진 내부적으로는 프로토타입 방식으로 작동된다.

- Class는 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.

 

클래스 내에서 정의한 메서드는 User.prototype에 저장한다.

class User {
    constructor(first, last) {
        this.firtstName = first;
        this.lastName = last;
    }
    getFullName(){
        return `${this.firtstName} ${this.lastName}`;
    }
}
 
const link2me = new User('Link2Me''Json');
link2me.getFullName();
 
console.log(link2me); // User { firtstName: 'Link2Me', lastName: 'Json' }
console.log(link2me.getFullName()); // Link2Me Json

new User('Link2Me', 'Json') 을 호출하면

1. 새로운 객체가 생성된다.

2. 넘겨받은 인수와 함께 constructor 가 자동으로 실행된다. 매개변수가 변수에 할당된다.

3. 객체의 메서드를 호출하면 메서드를 prototype 프로퍼티를 통해 가져온다.

    이 과정이 있기 때문에 객체에서 클래스 메서드에 접근할 수 있다.

 

클래스는 함수이다. alert(typeof User);

 

정확히는 생성자 메서드와 동일하다.
alert(User === User.prototype.constructor); // true

클래스 내부에서 정의한 메서드는 User.prototype에 저장된다.
alert(User.prototype.getFullName);

현재 프로토타입에는 메서드가 두 개다.
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, getFullName

 

클래스 상속

// 클래스 구현 : 자바스크립트에서 클래스 사용은 ES6에서부터 지원
class Parent {
    sayHello() {
        return 'Hello world, from Parent Class';
    }
}
 
// 클래스 상속
class Child extends Parent {
}
 
const child = new Child();
console.log(child.sayHello());

 

 

 
class Person {
  constructor(name) {
    this.name = name;
  }
  sayHello() {
    console.log(`hello~ ${this.name}!`);
  }
 
  // 부모 클래스에서 클래스 필드로 메서드를 정의하면
  // 자식에서 super를 사용해서 호출할 수 없다.
  // 이 메서드는 프로토타입에 추가되는 것이 아니고, 객체에 추가된다.
  getRandom = () => {
    return Math.floor(Math.random() * 10);
  };
}
 
class Programmer extends Person {
  constructor(name, language) {
    super(name);
    this.language = language;
  }
  sayHello() {
    super.sayHello();
    console.log(`I like ${this.language}.`);
    console.log(`Your lucky number is ${super.getRandom()}`);
    // super는 프로토타입을 기반으로 동작한다.
    // super로 접근하려고 하면 에러가 발생한다. this 로 변경해보라.
  }
 
  // this로 자식에서도 찾고자 한다면 클래스 필드로 정의하면 된다.
  // getRandom = () =>
  getRandom() {
    return 20 + Math.floor(Math.random() * 10);
  }
}
 
const person1 = new Programmer('mike''javascript');
person1.sayHello();
 

 

 

 

class Person {
    age = 25;
    constructor(name) {
        this.name = name;
    }
    sayHello() { // this 인식
        console.log(`hello~ ${this.name}!`);
    }
 
    arrowName = () => {
        console.log(this.name);// this 인식
    };
 
    normalName = function(){
        console.log(this.name); // undefined
    }
}
 
class Programmer extends Person {
    constructor(name, language) {
        super(name);
        this.language = language;
    }
    sayHello() { // 메서드 오버라이딩
        super.sayHello();
        console.log(`${this.name}은 ${this.language} 언어를 좋아합니다.`);
    }
}
 
const p1 = new Person('강감찬');
p1.sayHello();
 
const p2 = new Programmer('홍길동''javascript');
p2.sayHello();
 
console.log(Person.prototype.age, Person.prototype.arrowName); // undefined undefined
console.log(Person.prototype.age, Person.prototype.normalName); // undefined undefined
 
const person1 = new Person('mike');
const person2 = new Person('jane');
person1.age = 50;
console.log(person1.age, person2.age); // 50 25
 
setTimeout(person1.arrowName, 100); // mike
setTimeout(person1.normalName, 100); // undefined
setTimeout(person2.arrowName, 100); // jane
setTimeout(person2.normalName, 100); // undefined
 

 

 

728x90
블로그 이미지

Link2Me

,

React Query String

React/React 2022. 6. 8. 00:05
728x90

http://localhost:3000/about?name=react&id=123 와 같은 URL 입력값에서 Query String을 추출하는 함수 예제이다.

React 강의를 듣고 그대로 타이핑을 하는데 동작이 안된다. 오래된 버전이라 그런가???

구글링을 해보고 그대로 실행해보는데도 역시 안되는 것들이 있다.

react-router-dom v6 에 맞게 구현해야 동작된다.

import React, {useState} from 'react';
import { useLocation } from 'react-router';
import qs from "query-string";  // npm install query-string
 
 
const About = () => {
    // In React Hooks:
    const searchParams = useLocation().search;
    console.log(searchParams);
    const query = qs.parse(searchParams);
    console.log(query);
 
    const name = new URLSearchParams(searchParams).get('name');
    const id = new URLSearchParams(searchParams).get('id');
    console.log({ name, id });
 
    return (
        <div>
            <h2>About 페이지입니다.</h2>
            {query.name && <p>name 은 {query.name} 입니다.</p>}
        </div>
    );
};
 
// https://everttimberg.io/blog/custom-react-hook-query-state/ 참고하자.
 
export default About;

 

비구조화 할당 문법을 통해 props 내부 값 추출하기

import {Route, Routes, useParams} from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
 
function App() {
    const { id } = useParams();
    return (
        <Routes>
            <Route path="/" element={<Home />}/>
            <Route path="/profile" element={<Profile/>}/>
            <Route path="/profile/:id" element={<Profile/>}/>
            <Route path="/about" element={<About name={"React"/>}/>
        </Routes>
    );
}
 
export default App;

 

props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며,

컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다.

{props.name} 대신에 {name} 으로 내부 값을 바로 추출하는 방법 : const { name } = props;

import React, {useState} from 'react';
import { useLocation } from 'react-router';
import qs from "query-string";  // npm install query-string
 
 
const About = props => {
    // In React Hooks:
    const searchParams = useLocation().search;
    console.log(searchParams);
    const query = qs.parse(searchParams);
    console.log(query);
 
    //const name = new URLSearchParams(searchParams).get('name');
    //const id = new URLSearchParams(searchParams).get('id');
    //console.log({ name, id });
 
    const { name } = props; // 비구조화 할당 문법
 
    return (
        <div>
            <h2>{name} About 페이지입니다.</h2>
            {query.name && <p>name 은 {query.name} 입니다.</p>}
        </div>
    );
};
 
 
export default About;

리액트에는 두가지 종류의 state가 있다.

하나는 클래스형 컴포넌트가 지니고 있는 state 이고,

다른 하나는 함수 컴포넌트에서 useState라는 함수를 통해 사용하는 state이다.

 

 

728x90

'React > React' 카테고리의 다른 글

React-bootstrap Header.js 테스트  (0) 2022.08.21
React CORS error 해결 방법  (0) 2022.08.20
React Router v6  (0) 2022.06.07
React useState  (0) 2022.06.04
React 값 전달(부모 → 자식, 자식 → 부모)  (0) 2022.06.03
블로그 이미지

Link2Me

,

React Router v6

React/React 2022. 6. 7. 06:34
728x90

웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것을 의미한다.

react-router-dom 버전 6 에서는 element 로 컴포넌트를 만들어야 동작하고, component 로 된 것은 에러 발생하고 동작되지 않는다.

V6 에서는 Switch 가 사라지고, Routes 로 대체되었다. 

Routes는 기존 Switch 처럼 경로 순서를 기준으로 선택하는 것이 아닌, 가장 일치하는 route 기반으로 선택하게 된다.

useHistory 가 사라지고, useNavigate 로 대체되었다.

- useNavigate로 기존에 useHistory의 기능을 전부 대체 가능하다.
- useHistory의 history는 객체였지만 useNavigate의 navigate는 함수다.
Route에 children, component가 사라지고, element 사용한다.

 

npm install react-router-dom // 라이브러리 설치

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from "react-router-dom";
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
 
reportWebVitals();

 

Route에 exact Prop 사라졌다. exact가 기본으로 되어있다.

기존 Route는 꼭 Switch 가 상위 요소로 없어도 되지만, v6의 Route는 Routes의 직속 자식이어야 한다.

import {Route, Routes, useParams} from "react-router-dom";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import About from "./pages/About";
 
function App() {
    const { id } = useParams();
    return (
        <Routes>
            <Route exact={true} path="/" element={<Home />}/>
            <Route path="/profile" element={<Profile/>}/>
            <Route path="/profile/:id" element={<Profile/>}/>
            <Route path="/about" element={<About/>}/>
        </Routes>
    );
}
 
export default App;

 

Link 는 컴포넌트, to 는 props

import React from 'react';
import {Link} from "react-router-dom";
 
const Home = () => {
    return (
        <div>
            <h1>Home 페이지입니다.</h1>
            <Link to={"/about?name=react"}>소개</Link>
        </div>
    );
};
 
export default Home;

 

Profile = (props) => 를 사용하지 말라.

http://localhost:3000/profile/4 를 해보면 결과를 확인할 수 있다.

import React from 'react';
import {useParams} from "react-router-dom";
 
const Profile = () => {
    // react-router-dom 버전 6부터는 element로 컴포넌트를 만들고
    // route props(match, history, location)을 받지 않는다.
    // useParams, useLocation, useHistory를 사용하여 route context에 접근한다.
    // let id = props.match.params.id 를 사용하면 에러 발생한다.
    const { id } = useParams();
    return (
        <div>
            <h1>Profile 페이지입니다.</h1>
            {id && <h3>ID: {id}</h3>}
        </div>
    );
};
 
export default Profile;

 

Query String 에 대한 사항은 다음 게시글을 읽어보면 된다.

https://link2me.tistory.com/2177

 

 

 

728x90

'React > React' 카테고리의 다른 글

React CORS error 해결 방법  (0) 2022.08.20
React Query String  (0) 2022.06.08
React useState  (0) 2022.06.04
React 값 전달(부모 → 자식, 자식 → 부모)  (0) 2022.06.03
React Event 처리하기  (0) 2022.05.29
블로그 이미지

Link2Me

,

React useState

React/React 2022. 6. 4. 00:05
728x90

Hook은 React 버전 16.8(2019년)부터 React 요소로 새로 추가되었다.

https://ko.reactjs.org/docs/hooks-effect.html 가 React 에서 기본 제공하는 내용 설명이다.

함수형 컴포넌트의 주요 단점은 state 와 라이프사이클 API 의 사용이 불가능하다는 점이었는데, 리액트 16.8 업데이트 이후 Hooks 기능이 도입되면서 해결되었다.

현재 리액트 공식 매뉴얼에서는, Class형 컴포넌트보다는 Function형 컴포넌트와 Hooks로 React 프로젝트를 만들기를 권장하고 있다.

 

App.js

import logo from './logo.svg';
import './App.css';
import Example1 from "./components/Example1";
import Example2 from "./components/Example2";
import Example3 from "./components/Example3";
 
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Example1 />
        <Example2 />
        <Example3 />
      </header>
    </div>
  );
}
 
export default App;

 

Example1.jsx

파일명을 생성하고 파일 안에서 rcc 를 입력하고 TAB 키를 누르면 자동완성된 기본 컴포넌트가 만들어진다.

클래스형 컴포넌트에서는 render함수가 꼭 있어야 한다.

import React, {Component} from 'react';
 
class Example1 extends Component {
    state = {count: 0};
 
    render() {
        const { count } = this.state;
        return (
            <div>
                <p>You clicked {count} times.</p>
                <button onClick={this.click}>Click me</button>
            </div>
        );
    }
 
    click = () => {
        this.setState({
            count: this.state.count + 1
        });
    };
}
 
export default Example1;

 

Example2.jsx

- useState 함수의 인자에는 상태의 초기값을 넣어 준다. 초기값은 숫자, 문자열, 객체, 배열 등

- 배열 비구조화 할당 const [count, setCount] 에서 첫번째 원소는 현재 상태이고, 두번째 원소는 상태를 바꾸어주는 함수이다. 이 함수를 Setter 함수라고 부른다.

- 하나의 useState 함수는 하나의 상태 값만 관리할 수 있다.

  컴포넌트에서 관리해야 할 상태가 여러 개라면 useState를 여러 번 사용하면 된다.

- state 는 컴포넌트 자체적으로 지닌 값으로 컴포넌트 내부에서 값을 업데이트할 수 있다.

import React from 'react';
 
const Example2 = () => {
    const [count, setCount] = React.useState(0);
 
    function click() {
        setCount(count + 1);
    }
 
    return (
        <div>
            <p>You clicked {count} times.</p>
            <button onClick={click}>Click me</button>
        </div>
    );
};
 
export default Example2;

 

Exampe3.jsx

// rsc 입력하고 Tab 키를 누른다.
import React from 'react';
 
const Example3 = () => {
    // useState : state를 대체할 수 있다.
    const [state, setState] = React.useState({count: 0});
 
    function click() {
        setState((state) => ({
            count: state.count + 1,
        }));
    }
 
    return (
        <div>
            <p>You clicked {state.count} times.</p>
            <button onClick={click}>Click me</button>
        </div>
    );
};
 
export default Example3;

 

 

이제 bootstrap4 를 적용해보자.

# Step1 – Install Bootstrap 4
npm install bootstrap --save

 

App.js

import logo from './logo.svg';
import './App.css';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import Example1 from "./components/Example1";
import Example2 from "./components/Example2";
import Example3 from "./components/Example3";
 
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Example1 />
        <Example2 />
        <Example3 />
      </header>
    </div>
  );
}
 
export default App;

 

 

Exampl1.jsx

import React, {Component} from 'react';
 
class Example1 extends Component {
    state = {count: 0};
 
    render() {
        const { count } = this.state;
        return (
            <div className="col-md-12 text-center">
                <p>You clicked {count} times.</p>
                <button className="btn btn-primary" onClick={this.click}>Click me</button>
            </div>
        );
    }
 
    click = () => {
        this.setState({
            count: this.state.count + 1
        });
    };
}
 
export default Example1;

 

 

 

728x90

'React > React' 카테고리의 다른 글

React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
React 값 전달(부모 → 자식, 자식 → 부모)  (0) 2022.06.03
React Event 처리하기  (0) 2022.05.29
React Component 만들기  (0) 2022.05.28
블로그 이미지

Link2Me

,
728x90

React Component 에서 값을 전달하는 방법이다.

자식 → 부모 데이터 전달

props : 상위 컴포넌트에서 하위 컴포넌트로 값을 전달하는 수단

- 하위 컴포넌트에서 상위 컴포넌트로 값을 전달할 수 없다.

- 하위 컴포넌트에서 상위 컴포넌트가 전달해준 값에 접근할 수 있게 해준다.

 

const [스테이트 값, 스테이트 변경 함수] = useState(스테이트 초기값);

import React, {useState} from 'react';
import Child from "./Child";
 
const Parent = () => {
    const [data, setData] = useState(0);
    // 1. 부모 컴포넌트에서 useState 를 통해 전달받은 데이터를 저장할 변수를 선언한다.
    // 2. 부모 컴포넌트에서 props로 함수를 넣어주면,
    //    자식 컴포넌트에서 그 함수를 이용해 값을 전달한다.
 
    const parentFnc = (data) => {
      setData(data);
    }
 
    return (
        <div>
            <div>부모 컴포넌트 값 : {data}</div>
            <Child number={data} getData={parentFnc} />
        </div>
    );
};
 
export default Parent;

 

Child 컴포넌트

Event Handling

- camelCase 로만 사용할 수 있다. onClick, onMouseEnter

- 이벤트에 연결된 자바스크립트 코드는 함수이다. onClick={함수}

- 실제 DOM 요소들에만 사용 가능하다.

import React from 'react';
 
const Child = props => {
    const onClick = () => {
      console.log(props.number);
      props.getData(props.number + 1);
    }
 
    return (
        <div>
            <button onClick={onClick}>+자식버튼</button>
        </div>
    );
};
 
export default Child;

Child 컴포넌트를 아래와 같이 수정 가능하다.

import React from 'react';
 
const Child = props => {
    const {number, getData} = props; // 비구조화 할당 문법
 
    const onClick = () => {
        console.log(number);
        getData(number + 1);
    };
 
    return (
        <div>
            <button onClick={onClick}>+자식버튼</button>
        </div>
    );
};
 
export default Child;

 

import Parent from "./components/Parent";
 
function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}
 
export default App;

 

부모 → 자식 데이터 전달

 

 

 

 

 

 

 

728x90

'React > React' 카테고리의 다른 글

React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
React useState  (0) 2022.06.04
React Event 처리하기  (0) 2022.05.29
React Component 만들기  (0) 2022.05.28
블로그 이미지

Link2Me

,
728x90

React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리 방식과 매우 유사하다.
- React의 이벤트는 소문자 대신 캐멀 케이스(camelCase)를 사용한다.
- JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다.

- DOM 요소에만 이벤트 설정이 가능하다. div, button, input, form, ul, li, span 등

- React Component 에는 이벤트 설정이 불가능하다.

 

Event Handler 예제

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta name="theme-color" content="#000000"/>
    <title>React App Sample</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
    class Component extends React.Component {
        constructor(props) {
            super(props);
            this.state = {count: 0};
            this.click = this.click.bind(this);
        }
 
        render() {
            return (
                <div>
                    <h3>{this.props.item}</h3>
                    <p>{this.state.count}</p>
                    <button onClick={this.click}>클릭</button>
                </div>
            );
        }
 
        click() {
            console.log("clicked");
            this.setState((state) => ({
                ...state,
                count: state.count + 1,
            }));
        }
    }
 
    // 사용
    ReactDOM.render(
        <Component item={"Front-End : React"}/>,
        document.querySelector('#root')
    );
</script>
</body>
</html>

 

여기에 버튼의 명칭이 ON, OFF 가 번갈아 가면서 나오도록 하는 걸 추가해보자.

<script type="text/babel">
    class Component extends React.Component {
        constructor(props) {
            super(props);
            this.state = {count: 0, isToggleOn: true};
            this.click = this.click.bind(this);
        }
 
        click() {
            console.log("clicked");
            this.setState((state) => ({
                ...state,
                count: state.count + 1,
                isToggleOn: !state.isToggleOn
            }));
        }
 
        render() {
            return (
                <div>
                    <h3>{this.props.item}</h3>
                    <p>{this.state.count}</p>
                    <button onClick={this.click}>{this.state.isToggleOn ? 'ON' : 'OFF'}</button>
                </div>
            );
        }
 
    }
 
    // 사용
    ReactDOM.render(
        <Component item={"React Event Handler"}/>,
        document.getElementById('root')
    );
</script>

 

 

 

 

 

 

 

 

728x90

'React > React' 카테고리의 다른 글

React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
React useState  (0) 2022.06.04
React 값 전달(부모 → 자식, 자식 → 부모)  (0) 2022.06.03
React Component 만들기  (0) 2022.05.28
블로그 이미지

Link2Me

,
728x90

https://ko.reactjs.org/docs/react-component.html 에 기본적인 React Component 사항을 확인한다.

 

 

컴포넌트는 소프트웨어의 재사용성을 높이고 유지보수를 용이하게 하기 위해 나온 기술이다.

컴포넌트는 두 가지 인스턴스 속성으로 props와 state를 가지고 있다.

props는 부모 컴포넌트가 자식 컴포넌트에게 주는 값이다.
어떠한 값을 컴포넌트에 전달해 줘야 할때 사용하며 할당된 후 컴포넌트 내부에서 값을 변경할 수 없다.
state는 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있다. 동적인 데이터를 다룰 땐 state를 사용한다.

둘(props, state)다 변경이 되면, render 가 다시 일어날 수 있다.

 

Class Component 예제1

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>React App Sample</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
  //console.log(React);
  //console.log(ReactDOM);
 
  // 리액트 컴포넌트는 리엑트로 만들어진 앱을 이루는 최소한의 단위
  // 컴포넌트는 데이터(props)를 입력받아 View(state) 상태에 따라 DOM Node를 출력하는 함수
  // 컴포넌트 이름은 항상 대문자로 시작해야 한다. 
// 소문자로 시작하는 컴포넌트는 DOM 태그로 취급하기 때문이다.
 
  // Class Component 정의
  class ClassComponent extends React.Component {
      // render() 메서드는 클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드
      render() {
          return <div>Hello React world.</div>;
      }
  }
 
  // 사용
  ReactDOM.render(
      <ClassComponent />,
      document.querySelector('#root')
  );
</script>
</body>
</html>

 

Function Component 예제1

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>React App Sample</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
  // 컴포넌트 이름은 항상 대문자로 시작해야 한다. 
// 소문자로 시작하는 컴포넌트는 DOM 태그로 취급하기 때문이다.
 
  // Function Component 정의
  function FunctionComponent() {
      return <div>Hello, React world.</div>;
  }
 
  // 화살표 함수 컴포넌트 정의
 const FunctionComponent2 = () => <div>Hello, React world.</div>;
 
  // 사용
  ReactDOM.render(
      <FunctionComponent />,
      document.querySelector('#root')
  );
</script>
</body>
</html>

 

React createElement 로 컴포넌트 만들기 예제

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>React App Sample</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
  // 컴포넌트 이름은 항상 대문자로 시작해야 한다. 
  // 소문자로 시작하는 컴포넌트는 DOM 태그로 취급하기 때문이다.
 
  const Component = () => {
    return React.createElement('p'null, `type 이 "React 컴포넌트" 입니다.`);
    // React.createElement(태그, props, childeren)
  }
 
  // 사용
  ReactDOM.render(
      React.createElement(Component, nullnull),
      document.querySelector("#root")
  );
</script>
</body>
</html>

 

위 예제는 태그가 여러개 일 경우 처리하는데 상당히 어렵다.

https://babeljs.io/ 사이트에서 직접 입력해보면...

자동으로 React.createElement 를 생성해주는 걸 확인할 수 있다.

 

React 에서 사용하는 JSX 문법

- 최상위 요소가 하나여야 한다.

- 자식들을 바로 랜더링하고 싶으면, <>자식들</>를 사용한다.

- 자바스크립트 표현식을 사용하려면 {표현식}을 이용한다.

- if 문을 사용할 수 없기 때문에 삼항연산자 혹은 &&를 사용한다.

- style을 이용해 인라인 스타일링이 가능하다.

- class 대신 className을 사용해 class를 적용할 수 있다.

- 자식요소는 엄격하게 쌍으로 닫아야 하고, 자식요소가 없다면 열면서 닫아야 한다. <br />

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>React App Sample</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
  // 사용
  ReactDOM.render(
      <div>
          <div>
              <h2>Front-end Frameworks</h2>
              <ul>
                  <li>React</li>
                  <li>Angular</li>
                  <li>Vue.js</li>
              </ul>
          </div>
      </div>,
      document.querySelector("#root")
  );
</script>
</body>
</html>

 

함수형 컴포넌트로 만들어서 바꾸면

<script type="text/babel">
  function Component() {
      return (
          <div>
              <div>
                  <h2>Front-end Frameworks</h2>
                  <ul>
                      <li>React</li>
                      <li>Angular</li>
                      <li>Vue.js</li>
                  </ul>
              </div>
          </div>
      )
  }
 
  // 사용
  ReactDOM.render(
      <Component />,
      document.querySelector("#root")
  );
</script>

 

이제 값을 전달하는 컴포넌트를 구현하는 간단 예제이다.

<script type="text/babel">
  function Component(props) {
      return (
          <div>
              <div>
                  <h2>Front-end Frameworks</h2>
                  <ul>
                      <li>{props.item}</li>
                      <li>Angular</li>
                      <li>Vue.js</li>
                  </ul>
              </div>
          </div>
      )
  }
 
  // 사용
  ReactDOM.render(
      <Component item="리액트" />,
      document.querySelector("#root")
  );
</script>

 

class 컴포넌트 값 전달 예제

전달하는 값이 없으면 기본으로 지정된 값이 보이는 걸 확인할 수 있다.

<Component item="React" />  라고 값을 지정하면 지정된 값이 출력되는 걸 확인할 수 있다.

<script type="text/babel">
    class Component extends React.Component {
        render(){
            return (
                <div>
                    <div>
                        <ul>
                            <li>{this.props.item}</li>
                        </ul>
                    </div>
                </div>
            )
        }
 
        static defaultProps = {
            item : "Vue.js"
        };
    }
 
    // 사용
    ReactDOM.render(
        <Component />,
        document.querySelector('#root')
    );
</script>

 

state

<script type="text/babel">
    class Component extends React.Component {
        // state = {
        //     count: 0,
        // }
 
        constructor(props) {
            super(props);
            this.state = { count: 0}
        }
 
        render() {
            return (
                <div>
                    <ul>
                        <li>{this.props.item}</li>
                        <li>{this.state.count}</li>
                    </ul>
                </div>
            );
        }
 
        componentDidMount() {
            setTimeout(() => {
                this.setState({
                    count: this.state.count + 1,
                });
            }, 1000);
        }
 
        static defaultProps = {
            item: "React"
        };
    }
 
    // 사용
    ReactDOM.render(
        <Component/>,
        document.querySelector('#root')
    );
</script>

 

componentDidMount 처리를 다르게 하는 법

<script type="text/babel">
    class Component extends React.Component {
        constructor(props) {
            super(props);
            this.state = { count: 0}
        }
 
        render() {
            return (
                <div>
                    <ul>
                        <li>{this.props.item}</li>
                        <li>{this.state.count}</li>
                    </ul>
                </div>
            );
        }
 
        componentDidMount() {
            setTimeout(() => {
                this.setState((previousState)=>{
                    const newState = { count: previousState.count + 1}
                    return newState;
                });
            }, 1000);
        }
 
        static defaultProps = {
            item: "React"
        };
    }
 
    // 사용
    ReactDOM.render(
        <Component item={"Front-End : React"/>,
        document.querySelector('#root')
    );
</script>

 

 

 

 

 

728x90

'React > React' 카테고리의 다른 글

React Query String  (0) 2022.06.08
React Router v6  (0) 2022.06.07
React useState  (0) 2022.06.04
React 값 전달(부모 → 자식, 자식 → 부모)  (0) 2022.06.03
React Event 처리하기  (0) 2022.05.29
블로그 이미지

Link2Me

,
728x90

자바스크립트는 null과 undefined 타입을 제외하고 모든 것을 객체로 다룬다.
함수를 변수 or 다른 함수의 변수처럼 사용할 수 있다. 함수를 콜백함수로 사용할 경우, 함수의 이름만 넘겨주면 된다.
함수를 인자로 사용할 때 callback 처럼 () 를 붙일 필요가 없다는 것이다.

 

<script>
 
// 콜백(callback)
// 함수의 인수로 사용되는 함수
 
// setTimeout(함수, 시간)
 
function timeout(callback) {
    setTimeout(()=>{
        console.log('Callback function example');
        callback()
    }, 3000);
}
 
timeout(()=>{
    console.log('Done!');
});
 
</script>

 

 

<script>
 
let allUserData = [];
 
// 콘솔에 결과를 찍는 함수
function LogFunc(userData) {
    if ( typeof userData === "string") {
        console.log("string : " + userData);
    } else if ( typeof userData === "object") {
        for (var item in userData) {
            console.log(item + ": " + userData[item]);
        }
    }
}
 
// 두 개의 인자를 받아서 마지막에 콜백함수를 호출한다.
function getInput (options, callback) {
    allUserData.push (options);
    callback (options);
}
 
// getInput 함수를 호출할 때 , 우리는 LogFunc 함수의 이름을 인자로 넘긴다.
// LogFunc은 콜백함수가 되어 getInput 함수의 내부에서 동작 할 것이다.
getInput ({name:"배수지", items:"JavaScript"}, LogFunc);
getInput ("홍길동", LogFunc);
 
</script>

 

 

 

 

728x90

'React > morden javascript' 카테고리의 다른 글

자바스크립트 Object  (0) 2022.06.11
자바스크립트 호이스팅(Hoisting)  (0) 2022.06.10
Javascript this and Class  (0) 2022.06.09
javascript 화살표 함수(람다식)  (0) 2022.05.27
변수 유효범위(Variable Scope)  (0) 2022.05.27
블로그 이미지

Link2Me

,
728x90

ECMAScript6 (2015.6월)

자바스크립트에서 화살표 함수 사용법을 알아두자.

 

Node.js 생태계는 무척 잘 되어 있다. 즉 제공되는 기능을 적재적소에 잘 써먹기만 하면 대부분의 문제를 해결할 수 있다.

프론트엔드의 주요 역할은 HTML과 CSS를 이용한 퍼블리싱, 데이터 기반의 상호작용 가능한 UI 구현, 그리고 백엔드와의 HTTPS 통신 정도이다.

대부분의 복잡한 비즈니스 로직은 서버에 탑재된다. 서버(백엔드)는 다량의 데이터를 안전하게 보관하고 내부 동작 방식을 숨길 뿐만 아니라 여러 요청을 동시에 처리하는 데 최적화되어 있다.

 

화살표 함수에 대한 자세한 사항은 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Arrow_functions 를 참조하면 된다.

 

화살표 함수 표현(arrow function expression)은 전통적인 함수표현(function)의 간편한 대안이다.

기존의 함수 표현식에서 function 키워드를 삭제하고 인자를 받는 매개변수의 괄호()와 코드블록({}) 사이에 화살표(=>) 만 넣어주면 된다.

 

// () => { }   vs function() { }

 

let func = function(arg1, arg2, ...argN) {
  return expression;
};
 
// 축약버전 : 화살표 함수
let func = (arg1, arg2, ...argN) => expression

 

- 인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략할 수 있다.

let double = n => n * 2;

 

- 인수가 하나도 없을 땐 괄호는 생략할 수 없다.

// 일반 함수
const foo = function () { console.log("foo") }; // foo
 
// 화살표 함수
const foo = () => console.log("foo"); // foo

 

- 본문이 여러 줄로 구성되었다면 중괄호를 사용해야 하고, 반드시 return 으로 결과를 반환해야 한다.

let sum = (a, b) => {  // 중괄호는 여러 줄로 구성되어 있음을 알려준다.
  let result = a + b;
  return result; // 반드시 return 지시자로 결과값을 반환해주어야 한다.
};
 
console.log(sum(34)); // 7
 
let sum = (a, b) => a + b; // 

 

<script>
 
let sum = (a, b) => a + b;
 
/* 위 화살표 함수는 아래 함수의 축약 버전이다.
 
let sum = function(a, b) {
  return a + b;
};
 
*/
</script>

 

 

<script>
// 매개변수 지정 방법
    () => { ... } // 매개변수가 없을 경우
     x => { ... } // 매개변수가 한 개인 경우, 소괄호를 생략할 수 있다.
(x, y) => { ... } // 매개변수가 여러 개인 경우, 소괄호를 생략할 수 없다.
 
// 함수 몸체 지정 방법
=> { return x * x }  // single line block
=> x * x   // 함수 몸체가 한줄 구문이면 중괄호를 생략할 수 있으며 암묵적으로 return된다.
 
() => { return { a: 1 }; }
() => ({ a: 1 })  // 위 표현과 동일하다. 객체 반환시 소괄호를 사용한다.
 
() => {           // multi line block.
  const x = 10;
  return x * x;
};
 
</script>
 

 

 

<script>
 
// ES5
var arr = [123];
var pow = arr.map(function (x) { // x는 요소값
    return x * x;
});
 
console.log(pow); // [ 1, 4, 9 ]


// ES6
const arr = [123];
const pow = arr.map(x => x * x);
 
console.log(pow); // [ 1, 4, 9 ]
 
</script>

 

728x90

'React > morden javascript' 카테고리의 다른 글

자바스크립트 Object  (0) 2022.06.11
자바스크립트 호이스팅(Hoisting)  (0) 2022.06.10
Javascript this and Class  (0) 2022.06.09
javascript 콜백 함수(callback function)  (0) 2022.05.27
변수 유효범위(Variable Scope)  (0) 2022.05.27
블로그 이미지

Link2Me

,
728x90

자바스크립트에서 객체나 함수는 모두 변수(variable)이다.

 

var 키워드로 선언된 변수는 함수 레벨 scope를 따름
    함수 레벨 Scope (Function-level scope)
        함수 내에서 선언된 지역 변수는 함수 내에서만 유효
        함수 외부에서는 참조 불가

let, const 키워드로 선언된 변수는 블록 레벨 scope를 따름
    블록 레벨 Scope (Block-level scope)
        코드 블록 내에서 선언된 변수는 코드 블록 내에서만 유효, 코드 블록 외부에서는 참조 불가
        코드 블록 내부에서 선언한 변수는 지역 변수

 

<script>
// 변수 유효범위(Variable Scope)
let a = 3
function name() {
    let a = 20  // let 은 블럭 레벨 범위안에서 유효
    console.log(a)
}
console.log(a)  // 결과 : 3
name()  // 결과 : 20
console.log(a) // 결과 3
</script>

 

 

<script>
// 변수 유효범위(Variable Scope)
 
function name() {
    if (true) {
        let a = 20  // let 은 블럭 레벨 범위안에서 유효
    }
    console.log(a) // 블럭 레벨 범위 밖에 a 변수
}
 
name()  // 결과 : ReferenceError: a is not defined
 
</script>

 

형변환(Type conversion)

Falsy(거짓과 같은 값) : false, '', null, undefined, 0, -0, NaN

Truthy(참과 같은 값) : true, 'false', 1, 2, -12, ....

 

NaN (Not a Number) → 1 + undefined

 

728x90
블로그 이미지

Link2Me

,
728x90

최신 버전의 node.js 를 PC에 설치한다.

 

npm install -g npm@latest

 

npx create-react-app 프로젝트명

npx create-react-app blog

 

 

 

cd blog

개발용 서버 띄우기 : npm start

 

 

 

 

728x90

'React > React TOOL&TIP' 카테고리의 다른 글

[vscode] React 코드 자동 완성 및 Auto Import 설정  (0) 2022.10.15
블로그 이미지

Link2Me

,