타입스크립트(TypeScript)는 자바스크립트(JavaScript)를 기반으로 정적 타입 문법을 추가한 프로그래밍 언어이다.

 

자바스크립트는 C나 Java와 같은 C-family 언어와는 구별되는 아래와 같은 특성이 있다.
- Prototype-based Object Oriented Language
- Scope와 this
- 동적 타입(dynamic typed) 언어 혹은 느슨한 타입(loosely typed) 언어
이와 같은 특성은 클래스 기반 객체지향 언어(Java, C++, C# 등)에 익숙한 개발자를 혼란스럽게 하며 코드가 복잡해질 수 있고 디버그와 테스트 공수가 증가하는 등의 문제를 일으킬 수 있어 특히 규모가 큰 프로젝트에서는 주의하여야 한다.

TypeScript 또한 자바스크립트 대체 언어의 하나로써 자바스크립트(ES5)의 Superset(상위확장)이다. C#의 창시자인 덴마크 출신 소프트웨어 엔지니어 Anders Hejlsberg(아네르스 하일스베르)가 개발을 주도한 TypeScript는 Microsoft에서 2012년 발표한 오픈소스로, 정적 타이핑을 지원하며 ES6(ECMAScript 2015)의 클래스, 모듈 등과 ES7의 Decorator 등을 지원한다.

 

// TypeScript 전역 설치
npm install -g typescript

 

 

TypeScript 파일(.ts)은 브라우저에서 동작하지 않으므로 TypeScript 컴파일러를 이용해 자바스크립트 파일로 변환해야 한다. 최종적으로 런타임에서는 이렇게 출력된 JavaScript 코드를 구동시키게 된다.

tsc script 와 같이 입력하면 script.js 파일이 같은 폴더에 생성된다.

 

자바스크립트 오류

- 실행을 하면 원치 않는 결과를 반환하기도 한다.

const a = 3// 정수
const b = '5'// 문자열
console.log(a + b); // 결과 : 35
console.log(a * b); // 결과 : 15 (원치 않는 결과)

 

타입스크립트에서는

숫자면 숫자, 문자열이면 문자열이라고 타입을 선언해주어서 계산이 작동되지 못하게 하거나, 컴파일 전에 오류 메시지를 띄우게 한다.

위와 같이 에러라고 표시를 해주고 있다.

강제로 tsc ex001.ts 를 터미널 창에서 실행하면.... ES3 버전의 Javascript 파일로 만들어진다.

tsc ex001.ts -t ES2015 를 터미널 창에서 실행하면 ES5 버전의 Javasript 파일로 만들어진다.

 

폴더에 있는 모든 ts 파일을 한꺼번에 js 파일로 만들려면 아래와 같이 하면 된다.

이제부터는 터미널 창에서 tsc 만 입력하면 자동으로 js 파일로 변경해준다.

만약 tsc ex001.ts 라고 입력하면 tsconfig.json이 무시되므로 주의하자.

 

TypeScript는 정적 타입을 지원하므로 컴파일 단계에서 오류를 포착할 수 있는 장점이 있다. 

명시적인 정적 타입 지정은 개발자의 의도를 명확하게 코드로 기술할 수 있다. 이는 코드의 가독성을 높이고 예측할 수 있게 하며 디버깅을 쉽게 한다.

 

 

 

참고하면 도움되는 글

https://yozm.wishket.com/magazine/detail/1376/

 

TypeScript는 어떻게 공부해야 하나요? | 요즘IT

지금 현재 개발하는 상황을 보면 TypeScript는 피할 수 없는 하나의 대세가 된 것 같습니다. TypeScript가 나온 이후로 점점 TypeScript로 만들어지고 있는 라이브러리나 코드의 비중은 높아지고 있고 아

yozm.wishket.com

 

 

 

 

 

 

728x90

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

TypeScript any  (0) 2022.10.13
블로그 이미지

Link2Me

,

자바스크립트 정규표현식 생성

1. 생성자 방식

    RegExp 생성자 함수를 호출하여 사용할 수 있다.

// new RegExg(표현식)
const regexp1 = new RegExp("^abc");
 
// new RegExg(표현식, 플래그)
const regexp2 = new RegExp("^abc""gi");
const regexp1 = new RegExp(/^abc/i); // ES6
const regexp2 = new RegExp(/^abc/'i');
const regexp3 = new RegExp('^abc''i');

 

 

2. 리터럴 방식

// 정규표현식은 /로 감싸진 패턴을 리터럴로 사용한다.
// 정규 표현식 리터럴은 패턴(pettern)과 플래그(flag)로 구성된다.
const regexp1 = /^abc/;  // --> /패턴/
const regexp2 = /^abc/gi; // --> /패턴/플래그

 

 

자바스크립트 메소드

문법   설명
정규식.exec(문자열)                         일치하는 하나의 정보(Array) 반환
정규식.test(문자열)                           일치 여부(Boolean) 반환
문자열.match(정규식)                       일치하는 문자열의 배열(Array) 반환
문자열.search(정규식)                      일치하는 문자열의 인덱스(Number) 반환
문자열.replace(정규식,대체문자)     일치하는 문자열을 대체하고 대체된 문자열(String) 반환
문자열.split(정규식)                          일치하는 문자열을 분할하여 배열(Array)로 반환
생성자_정규식.toString()                  생성자 함수 방식의 정규식을 리터럴 방식의 문자열(String)로 반환

 

 

For example a(?=b) will match the "a" in "ab", but not the "a" in "ac".

Whereas a(?!b) will match the "a" in "ac", but not the "a" in "ab".

const regexr = /.+(?=:)/;  // positive 전방 탐색(lookahead)
const str = 'https://www.abc.com';
console.log(regexr.exec(str));  // 결과 : https
console.log(str.match(regexr)); // 결과 : https

 

const regexr = /.(?!.)/gi; // 부정형 전방탐색(negative lookahead)
const str = '홍길동';
console.log(regexr.exec(str));  // 결과 : 동
console.log(str.replace(regexr, '*')); // 결과 : 홍길*

 

정규표현식 기본적인 이해는 https://www.nextree.co.kr/p4327/ 를 참조하면 도움된다.

https://heropy.blog/2018/10/28/regexp/

728x90

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

Javascript Array.map 사용 예제  (2) 2022.12.27
카카오 맵 장소 검색 구현 방법  (1) 2022.12.19
[Javascript] _cloneDeep()  (0) 2022.10.05
[ES6] Spread 연산자  (0) 2022.10.02
자바스크립트 Object  (0) 2022.06.11
블로그 이미지

Link2Me

,

현재 폴더에 package.json 추가된다.
npm init –y

 

개발용 의존성 패키지 설치 : 개발할 때만 필요하다.  --save-dev 대신에 -D
npm install parcel-bundler –D

 

원하는 버전을 명시하여 버전 설치
npm install lodash@4.17.20

최신버전의 정보를 보여준다.
npm info lodash

package.json 이 있는 곳에서 명령어를 입력해야 한다.
npm update lodash

package.json 파일이 있으면 node_module 을 설치할 수 있다.
package.josn 파일과 package-lock.json 파일을 삭제되지 않게 조심해야 한다.
npm install

 

{
  "name""ex01",
  "version""1.0.0",
  "scripts": {
    "dev""parcel index.html",
    "build""parcel build index.html"
  },
  "keywords": [],
  "author""",
  "license""ISC",
  "description""",
  "dependencies": {
    "lodash""^4.17.21"
  },
  "type""module"
}

Cannot use import statement outside a module 와 같은 에러 메시지가 발생하면

위와 같이 package.json에  "type": "module" 을 추가해주면 해결된다.

 

형변환(Type conversion)
=== 일치연산자
== 동등연산자 : 형변환이 발생한다.

 

객체는 참조타입(reference type)이기 때문에 할당 연산자 (=) 를 사용하면 메모리 주소값이 복사된다.

Spread operator 를 사용하여 의도적으로 얕은 복사(Shallow Copy)를 할 수 있다.

깊은 복사는 lodash 모듈을 설치해서 이용하면 편리하다.

loash 에서 제공하는 얕은 복사 함수는 _.clone(object) 이다.

loash 에서 제공하는 깊은 복사 함수는 _.cloneDeep(object) 이다.

import _ from 'lodash';
 
const user = {
    name'홍길동',
    age : 25,
    emails: ['link2me@test.com']
}
 
const copyUser = _.cloneDeep(user);
console.log(copyUser === user); // 메모리 주소가 같은가?
 
user.age = 30;
user.emails.push('jsk005@test.com');
console.log('user', user);
console.log('copyUser', copyUser);

결과

 

 

 

 

 

 

 

 

 

728x90

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

카카오 맵 장소 검색 구현 방법  (1) 2022.12.19
[Javascript] 정규표현식  (0) 2022.10.08
[ES6] Spread 연산자  (0) 2022.10.02
자바스크립트 Object  (0) 2022.06.11
자바스크립트 호이스팅(Hoisting)  (0) 2022.06.10
블로그 이미지

Link2Me

,

ES6에서는  '...'와 같이 다소 특이한 형태의 문법이 추가되었다. 
점 3개가 연달아 붙어있는 이 표시는 Spread Opertor(스프레드 오퍼레이터, 전개 연산자)를 나타내는 것으로, 배열, 함수, 객체 등을 다루는 데 있어서 매우 편리하고 재미있는 새로운 기능을 제공한다.

 

const numbersOne = [123];
const numbersTwo = [456];
const numbersCombined = [...numbersOne, ...numbersTwo];

 

 

const numbers = [123456];
 
const [one, two, ...rest] = numbers;

컴마 개수 이후의 값이 rest 값이다.

 

const arr1 = [012];
const arr2 = [345];
 
// (1) 배열 복사
const arr3 = [...arr1]; // arr3은 [0, 1, 2]
 
// (2) 배열에 추가 요소로 넣기
const arr4 = [12, ...arr2, 910]; // arr4는 [1, 2, 3, 4, 5, 9, 10]
 
// (3) 두 배열 이어 붙이기
const arr5 = [...arr1, ...arr2]; // [0, 1, 2, 3, 4, 5];

 

728x90

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

[Javascript] 정규표현식  (0) 2022.10.08
[Javascript] _cloneDeep()  (0) 2022.10.05
자바스크립트 Object  (0) 2022.06.11
자바스크립트 호이스팅(Hoisting)  (0) 2022.06.10
Javascript this and Class  (0) 2022.06.09
블로그 이미지

Link2Me

,

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

,

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

,

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

,

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

,

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

,

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

,

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

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

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

,

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

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

,

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

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

웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 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

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

,

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

,

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

,

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

,

자바스크립트는 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

,