반응형

읽기전용(read only)


 // TODO: 1) 읽기 전용(readonly) : 값 수정 불가
    interface IHello {
        readonly name: string
    }

    let val: IHello = { name: "hello"}; // 초기값 정의
    // val.name = "hello2"; // 변경불가 (readonly)

 

read only 변수에 값을 변경할 수 없음

튜플(tuple)


 // TODO: 2) 튜플(tuple) : 정해진 자료형의 고정된 크기의 배열
    let tuple: [string, number] = ["a", 1];
    console.log("tuple", tuple);
    // tuple = ["a", 1, 2]; // 값이 3개가 들어와서 에러
    // tuple = [1, "a"]; // 자료형 순서가 맞지 않음 에러

결과값
값이 3개가 들어와서 에러가 발생함
자료형 순서가 맞지 않는 경우

 

 

enum : 열거형, 상수를 대체해서 사용


  // TODO: enum : 열거형, 상수를 대체해서 사용함
  // TODO: 아래 상수에 자동으로 0 ~ n 1씩 증가되어 저장됨, 값도 직접 지정 가능
  enum Week {
    Sun,        // Sun = 0을 할당함
    Mon,        // Mon = 1
    Tue,        // Tue = 2
    Wed = 5,    // Wed = 5 (개발자가 강제로 값을 저장)
    Thu,        // Thu = 6
    Fri,        // Fri = 7
    Sat,        // Sat = 8
  }
  console.log("Week", Week);
  console.log("Week", Week.Sun);

 

사용자지정 타입


  • 여러 타입을 변수에 저장해서 사용자지정 타입으로 만들기
// TODO: 4) 별명 붙이기
  // TODO: 사용법 : type 별명 = 자료형 | 자료형2 ...
  // TODO: let 변수명 : 별명 = 값;
  type aliasUser = string | number;
  let person : aliasUser = "hong";
  console.log(person);

타입추론


// TODO: 5) 타입추론 : 모든 변수에 자료형을 지정하지않아도 값으로 추론하는 기능을 부여

  // TODO: (1) 변수의 초기값 : 생략가능
  let num = 10;     // 사용가능

  // TODO: (2) 기본값이 있는 매개변수 : 생략가능
  // 모던자바스크립트 사용법 : function 함수명(매개변수, 매개변수2 = 0){}
  // 함수의 사용 : 함수명(1) => 함수명(1, 0)    
  function add(a:number, b = 0):number {
    return a + b;
  }

  // TODO: (3) 리턴자료형은 함수에서 생략가능
  function add2(a:number, b = 0) {
    return a + b;
  }

 

타입(자료형) 단언


  // TODO: 6) 타입(자료형) 단언 :
  // TODO: 활용 : 컴퓨터는 알 수 없으나 개발자는 확실히 그 변수의 자료형을 확신하면 사용가능
  // TODO: 사용법 : 변수 as 자료형
  function someFunc(val: string | number, isNumber: boolean) {
    // 가정 : isNumber 가 true이면 무조건 val 값은 정수가 된다고 확신
    if (isNumber === true) {
      (val as number).toFixed(2);
    }
  }
반응형

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

typescript - 함수  (0) 2023.09.06
typescript  (0) 2023.09.06
메모이제이션  (0) 2023.09.02
State(useState)  (0) 2023.08.31
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
반응형

typescript에서의 함수 정의


// Func.tsx

import React from "react";
import { useState } from "react";

function Func() {
  // TODO: 변수 정의
  let [name, setName] = useState<string>("");
  let [message, setMessage] = useState<string>("");

  // TODO: 함수 정의 : 타입스크립트 적용
  // 매개변수 2개를 전달받아 message 변수에 저장하는 함수
  // getInputVal("안녕하세요", 2023)
  // TODO: 사용법 : const 함수명 = (매개변수: 자료형, ...): 리턴자료형 => {}
  const getInputVal = (arg: string, year: number): void => {
    setMessage(`${arg} 현재는 ${year} 년도 입니다.`); // message(화면 바인딩)
  };

  // 역바인딩(이벤트) 함수 정의
  // TODO: const 함수명 = (event:이벤트자료형...): 함수리턴자료형 => {};
  const onChangName = (event: React.ChangeEvent<HTMLInputElement>): void => {
    setName(event.target.value);
  };

  return (
    <div className="container">
      <input
        className="form-control mt-3 mb-3 w-25"
        type="text"
        name="name"
        value={name}
        onChange={onChangName}
      />
      입력값 : {name}
      <br />
      {/* react 아래 onClick={함수명} // 매개변수가 없는 함수 */}
      {/* TODO: 이벤트 함수에 매개변수가 있으면 화살표함수를 사용해야함 */}
      {/* react 아래 onClick={()=>{함수명(매개변수, 매개변수2)}} // 매개변수가 있는 함수는 화살표함수사용 */}
      <button
        className="btn btn-primary mt-3 mb-3"
        onClick={() => getInputVal("안녕하세요", 2023)}
      >
        입력값
      </button>
      <br />
      {message}
    </div>
  );
}

export default Func;
매개변수를 전달받는 함수정의

const 함수명 = (매개변수:자료형...):리턴자료형 => { };

 

역바인딩(이벤트) 함수 정의

const 함수명 = (event:이벤트자료형) :리턴자료형 => { };

 

이벤트자료형을 쉽게 알아내는 방법

  • html 태그 쪽에 있는 onChange에 마우스를 올리면 VScode에서 이벤트자료형을 추천해주는데 위의 붉은색 박스부분을 복사합니다.

  • 복사한 내용을 역바인딩 함수의 이벤트 자료형에 붙혀줍니다.
  • 단 ChangeEventHandler 부분의 Handler 부분은 삭제해줍니다.

 

연습문제


위의 화면처럼 출력해봅시다.

[부트스트랩 cdn]

    <!-- bootstrap css link -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">

function FuncExam() {
return (
    <div className="container">
      <input
        className="form-control mt-3 mb-3 w-25"
        type="password"
        name="password"
        value={password}
        onChange={onChangPassword}
      />
      입력값 : {password}
      <br />
      <button
        className="btn btn-primary mt-3 mb-3"
        onClick={() => getInput("안녕하세요", 4, true)}
      >
        입력값
      </button>
      <br />
      {message}
    </div>
  );
}

export default FuncExam;

 

[정답]

  let [password, setPassword] = useState<string>("");
  let [message, setMessage] = useState<string>("");

  const getInput = (arg: string, day: number, bool: boolean): void => {
    setMessage(`${arg} 오늘날짜는 ${day} 일이 맞나요? 답은 ${bool} 입니다.`);
  };

  const onChangPassword = (
    event: React.ChangeEvent<HTMLInputElement>
  ): void => {
    setPassword(event.target.value);
  };
반응형

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

typescript - etc  (1) 2023.09.06
typescript  (0) 2023.09.06
메모이제이션  (0) 2023.09.02
State(useState)  (0) 2023.08.31
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
반응형

VS code에서 타입스크립트 프로젝트 생성방법


  • 폴더 생성 후 폴더 안에서 터미널 실행
  • 터미널에 npx create-react-app 프로젝트명 --template typescript 명령어 입력
  • 생성이 완료되면 리액트 서버 실행명령어 입력 npm start

프로젝트 생성완료가 되고 리액트 서버를 실행하면 위의 메시지가 출력됩니다.

typescript?


자바스크립트는 자료형을 정의하지 않고 자유롭게 변수에 값을 넣어 코딩이 가능합니다. 즉, 코딩이 간략하고 코딩생산성이 증가하지만 코딩시 에러를 잡지 못하고 서비스때 심각한 오류가 발생합니다.

 

즉 자바스크립트의 자료형을 명시해서 코딩하게 해주는 JS의 확장 언어를 타입스크립트라 합니다.

 

// Basic.tsx : 자식 컴포넌트(typescript 적용된 버전)
// rfce
import React, { useState } from 'react'
// 새로운 객체타입(자료형) 정의한 파일 import
import IObject from './../types/IObject';

function Basic() {
    // TODO: 타입스크립트 기본 사용법 익히기
    // 타입스크립트 바인딩 변수
    // 사용법 : let [변수명, set변수명] = useState<자료형>(초기값);
    let [message, setMessage] = useState<string>("바인딩 변수 출력입니다.");
    let [num, setNum] = useState<number>(0);
    let [bflag, setBflag] = useState<boolean>(true);
    let [obj, setObj] = useState<IObject>({id: null, name:"green"});
    let [arr, setArr] = useState<Array<number>>([1, 2, 3, 4, 5]);
    let [objArr, setObjArr] = useState<Array<IObject>>([{id: null, name: "green"}]);
   
    // TODO: 1) 기본자료형 : 문자열(string), 숫자(number), 참/거짓(boolean), 객체(따로정의)
    // 타입스크립트 일반 변수 정의
    // 사용법 : let 변수명: 자료형 = 값;
    let message2: string = "일반 변수 출력입니다."; // 문자열
    let num2: number = 1; // 숫자형(실수, 정수 모두 포함)
    let bflag2: boolean = false; // 참/거짓(bool, boolean)

    // TODO: 객체는 자료형을 개발자가 따로 정의해서 사용함
    // 사용법 let 변수명: 정의한객체파일명 = {속성:값...};
    // IObject = {id?: any(null제외한 어떤 자료형도 가능) | null, name: string(문자열만 가능)}
    // id는 모든 자료형 허용 또는 null 자료형도 허용 / name은 문자열만 허용
    let obj2: IObject  = {id: null, name:"green2"};   // 객체(object)

    // TODO: 2) 유니온 사용법 : let 변수명: 자료형(type) | 자료형2 ...
    let num3: number | string = 1;
    let num4: number | string = "hello";
    // let num5: number | string = true; // 에러 발생

    // TODO: 3) 옵셔널(?) : 객체의 속성이나 함수의 매개변수에 사용가능
    // TODO: 사용하면 오류없이 실행되게 함(자료형 | undefined 더 붙은 것과 같은 의미)
    function hello(name?: string) {
        console.log(`안녕하세요 ${name}`);
    }

    // 함수의 사용
    hello("홍길동"); // 안녕하세요 홍길동
    hello();        // 안녕하세요

    // TODO: 4) 배열 : let 변수: Array<자료형 | 자료형2 ...>
    // TODO: 변수 및 함수 사용 시 반드신 정의된 자료형의 값으로 사용하게 강제함
    let arr2: Array<string> = ["a", "b", "c"];     // 문자열 배열
    let arr3: Array<any> = [1, 2, 3];              // 모든 자료형 사용가능
    let arr4: Array<number> = [1, 2, 3];           // 숫자형 사용가능
   
    // TODO: 객체 배열
    let objArr2: Array<IObject> = [{ id: 1, name: "green2"}]; // JSON 문서 형태(객체배열)

  return (
    <div>
        문자(일반) : {message2}<br/>
        문자(바인딩) : {message}<br/>

        숫자형(일반) : {num2}<br/>
        숫자형(바인딩) : {num}<br/>

        boolean형(일반) : {bflag2? "참":"거짓"}<br/>
        boolean형(바인딩) : {bflag? "참":"거짓"}<br/>

        객체형(일반) : {obj2.name}<br/>  
        객체형(바인딩) : {obj.name}<br/>  

        배열(일반) : {arr2}<br/>  
        배열(바인딩) : {arr}<br/>

        {/* 객체배열은 반복문으로 출력 : .map((value, index)=>{}) */}
        객체배열(일반) : {objArr2.map((value)=>value.name)}<br/>  
        객체배열(바인딩) : {objArr.map((value)=>value.name)}<br/>  



    </div>
  )
}

export default Basic

객체형의 경우 개발자가 따로 정의를 해주어야 합니다.

 

// types폴더 > IObject.ts 객체 자료형을 정의하는 파일
// TODO: 타입스크립트 파일명 종류 : .tsx(jsx표현식을 사용한 js), .ts(jsx 표현식을 사용 안 한 js파일)
// TODO: 리액트의 JSX(Javascript and XML) : {값}
// 사용법
// export default interface 객체자료형명 {
//                  속성 : 자료형 | 자료형2 ...,
//                  속성2 : 자료형
// }
// 속성? : 옵셔널(?) : 속성이 없어도 오류 없이 실행되게 해줌
// 예) let obj: IObject = { name: "홍길동"}
//    obj.id (결과는 오류로 출력되지만 에러없이 프로그램이 실행되게 해줌)
export default interface IObject {
    id?: any | null,
    name: string
}

 

연습문제


// BasicExam.tsx : 자식컴포넌트
import React from "react";
import { useState } from "react";

function BasicExam() {
  let [message, setMessage] = useState<string>(
    "안녕하세요 그린컴퓨터아카데미입니다."
  );
  let [message2, setMessage2] = useState<string>("아래는 곱셈 샘플입니다.");
  let [message3, setMessage3] = useState<string>("곱셈");
  let [num, setNum] = useState<number>(2);
  let [num2, setNum2] = useState<number>(3);
  let [result, setResult] = useState<number>(num * num2);

  return (
    <div>
      {/* 아래 처럼 바인딩 변수를 사용해서 화면 출력을 하되 타입스크립트 코드를 적용하여 출력하세요
        단, 문자는 string , 숫자는 number 를 사용해서 코딩하세요
        */}
      {/* 결과 :
                안녕하세요 그린컴퓨터아카데미입니다.
                아래는 곱셈 샘플입니다.
                곱셈
                2 * 3 = 6
               
         */}
      {message}
      <br />
      {message2}
      <br />
      {message3}
      <br />
      {`${num} * ${num2} = ${result}`}
      <br />
    </div>
  );
}

export default BasicExam;

반응형

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

typescript - etc  (1) 2023.09.06
typescript - 함수  (0) 2023.09.06
메모이제이션  (0) 2023.09.02
State(useState)  (0) 2023.08.31
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
반응형

React.memo


컴포넌트, 변수, 함수 등을 재렌더링 할 때 제어가 필요한 경우 메모이제이션을 수행합니다.

 

메모이제이션이란 이전 처리 결과를 저장해둠으로써 처리속도를 높이는 기술입니다.

 

즉, 필요할 때만 다시 계산하게 하여 불필요한 처리를 줄입니다.

 

컴포넌트를 메모이제이션해서 부모 컴포넌트가 재렌더링되더라도 자식 컴포넌트의 재렌더링을 방지합니다.

 

리액트 내의 memo를 사용하며 import를 해주어야 합니다 사용법은 컴포넌트 함수 전체를memo() 로 감싸면 됩니다.

 

 

[App.js]

import { useState, memo } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

//TODO: React.memo
// 리액트에서 컴포넌트, 변수, 함수 등을 재렌더링할 때 제어가 필요한 경우 메모이제이션을 수행
// 메모이제이션 : 이전 처리 결과를 저장, 처리속도를 높이는 기술, 필요할 때만 다시 계산하게 하여 불필요한 처리를 줄일 수 있음
// 사용법 : const 컴포넌트명 = memo(()=>{});
//         import memo from "react";

export const App = memo(() => {
  // 컴포넌트를 괄호로 감싸면 해당 컴포넌트는 props에 변경이 있을 때만 재렌더링됨
  console.log("App 렌더링");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };


  return (
    <>
      <button onClick={onClickButton}>버튼</button>
      <p>{num}</p>
      <Child1  />
      <Child4 />
    </>
  );
});

export default App;

[Child 1, 2, 3, 4]

import {Child2} from "./Child2";
import {Child3} from "./Child3";
import {memo} from "react";

const style = {
    height : "200px",
    backgroundColor : "lightblue",
    padding : "8px"
};

export const Child1 = memo((props) => {
    console.log("Child1 렌더링");
 

    return (
        <div style={style}>
            <p>Child 1</p>
            <Child2 />
            <Child3 />
        </div>
    );
 });
import {memo} from "react";
const style = {
  height: "50px",
  backgroundColor: "lightgray",
};

export const Child2 = memo(() => {
  console.log("Child2 렌더링");

  return (
    <div style={style}>
      <p>Child2</p>
    </div>
  );
});
import {memo} from "react";
const style = {
  height: "50px",
  backgroundColor: "lightgray",
};

export const Child3 = memo(() => {
  console.log("Child3 렌더링");

  return (
    <div style={style}>
      <p>Child3</p>
    </div>
  );
});
import {memo} from "react";
const style = {
  height: "200px",
  backgroundColor: "wheat",
  padding: "8px",
};

export const Child4 = memo(() => {
  console.log("Child4 렌더링");

  return (
    <div style={style}>
      <p>Child4</p>
    </div>
  );
});

[실행결과]

* 상단 버튼을 누르면 부모 컴포넌트인 App 부분만 재렌더링 되는 것을 볼 수 있으며 자식 컴포넌트 Child 1, 2, 3, 4는 재렌더링 되지 않는 것을 알 수 있습니다.

 

useCallback


memo를 사용해 컴포넌트를 메모이제이션 할 수 있습니다.

이번에는 함수 메모이제이션을 알아봅시다!

 

먼저 Child1에 리셋 버튼을 생성합니다.

리셋 버튼을 클릭하면 카운트 수치를 0으로 되돌리는 기능을 추가하면 됩니다.

카운트 수치의 state는 부모 컴포넌트인 App 이 가지고 있기 때문에 App 안에서 리셋하기 위한 함수를 정의하고 그 함수를 Child1에 전달하는 방식으로 구현합니다.

 

[App.js]

import { useState, memo } from "react";
import { Child1 } from "./components/Child1";
import { Child4 } from "./components/Child4";

//TODO: React.memo
// 리액트에서 컴포넌트, 변수, 함수 등을 재렌더링할 때 제어가 필요한 경우 메모이제이션을 수행
// 메모이제이션 : 이전 처리 결과를 저장, 처리속도를 높이는 기술, 필요할 때만 다시 계산하게 하여 불필요한 처리를 줄일 수 있음
// 사용법 : const 컴포넌트명 = memo(()=>{});
//         import memo from "react";

export const App = memo(() => {
  // 컴포넌트를 괄호로 감싸면 해당 컴포넌트는 props에 변경이 있을 때만 재렌더링됨
  console.log("App 렌더링");

  const [num, setNum] = useState(0);

  const onClickButton = () => {
    setNum(num + 1);
  };

  // 리셋함수 정의
  const onClickReset = () => {
    setNum(0);
   };

  return (
    <>
      <button onClick={onClickButton}>버튼</button>
      <p>{num}</p>
      {/* Child1에 props로 클릭함수를 전달 */}
      <Child1 onClickReset={onClickReset} />
      <Child4 />
    </>
  );
});

export default App;

[Child1.js]

import {Child2} from "./Child2";
import {Child3} from "./Child3";
import {memo} from "react";

const style = {
    height : "200px",
    backgroundColor : "lightblue",
    padding : "8px"
};

export const Child1 = memo((props) => {
    console.log("Child1 렌더링");

    // props로 부터 함수를 전개
    const {onClickReset} = props;

    return (
        <div style={style}>
            <p>Child 1</p>
            {/* onClick 속성 추가하고 함수 값 넣기 */}
            <button onClick={onClickReset}>리셋</button>
            <Child2 />
            <Child3 />
        </div>
    );
 });

[실행결과]

그러나 앞에서 최적화했던 재렌더링을 다시 확인해보면 카운트 업 할때마다 Child1이 재렌더링 되는 것을 알 수 있습니다.

함수를 Props에 전달할 때 컴포넌트를 메모이제이션해도 재렌더링되는 것은 

함수가 다시 생성되기 때문입니다. 일반적으로 우리가 함수를 정의할 때는 아래와 같이 정의합니다.

  // 리셋함수 정의
  const onClickReset = () => {
    setNum(0);
   };

 

이렇게 함수를 정의하면 재렌더링 등으로 코드가 실행될 때마다 항상 새로운 함수가 다시 생성됩니다.

따라서 함수를 Props로 받는 Child1 은 Props가 변화했다고 판정해 카운트업 할 때마다 재렌더링을 하게 되는 것입니다.

이 현상을 피하기 위해서는 함수에 메모이제이션을 해주어야 합니다.

 

리액트는 함수 메모이제이션 기능 useCallback을 제공합니다. useCallback은 첫번째 인수에 함수, 두번째 인수에 의존 배열을 받습니다.

 

그러면 Child1 에 리셋함수를 아래와 같이 변경해줍니다.

 

  // 리셋함수 정의 - useCallback 함수 사용
  const onClickReset = useCallback(() => {
    setNum(0);
   }, []);

 

변경 후 실행화면을 볼까요?

App 만 재렌더링되어 불필요한 재렌더링을 최적화하였습니다.

 

변수 메모이제이션


앞에서 컴포넌트 메모이제이션과 함수 메모이제이션에 대해 알아보았습니다.

기본적으로 이 두가지를 사용하면 불필요한 재렌더링을 제어할 수 있습니다. 

 

React.useMemo

memo나 useCallback 만큼은 자주사용하지는 않지만 리액트에서는 변수 메모이제이션으로 useMemo를 제공합니다.

useMemo 사용법은 아래와 같습니다.

 

   // 변수 메모이제이션
   const 변수명 = useMemo(()=>{
    // 실행부분 - 함수에 변수에 설정할 값의 반환
   },[의존배열]);
반응형

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

typescript - 함수  (0) 2023.09.06
typescript  (0) 2023.09.06
State(useState)  (0) 2023.08.31
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
map, filter  (0) 2023.08.31
반응형

State


리액트에서는 화면에 표시하는 데이터나 길이가 변하는 상태 등을 모두 State로 관리합니다.

웹 애플리케이션을 만들 때 화면은 다양한 상태를 가집니다. 예시는 다음과 같습니다.

  • 에러가 있는가?
  • 모달 창을 열고 있는가?
  • 버튼을 클릭했는가?
  • 텍스트 박스에 무언가를 입력했는가?

이와 같이 '상태'는 모두 State로 관리하며 이벤트가 실행되는 경우 등에 업데이트 처리를 수행함으로써 동적 애플리케이션을 구현합니다.

 

useState


useState는 리액트 안에서 제공되므로 사용할 때는 import해야 합니다.

 

import { useState } from "react";

useState 함수 반환값은 배열형태로 되어 있습니다. 첫번째에 State 변수, 두번째에 State를 업데이트하기 위한 함수가 설정됩니다.

 

  // State 정의
  const [변수명, set변수명] = useState(초기값);

버튼 클릭시 카운트업하는 기능을 구현해보겠습니다.

 

import { ColoredMessage } from "./components/ColoredMessage";
import { useState } from "react";

export const App = () => {
  // State 정의
  const [num, setNum] = useState(0);
 
  // 버튼 클릭 시 state를 카운트 업
  const onClickButton = () => {
    setNum(num + 1);
  };

 

 

  return (
    <>
      <h1 style={{ color: "red" }}>안녕하세요</h1>
      <ColoredMessage color="blue" message="잘 지내시죠?" />
      <ColoredMessage color="pink" message="잘 지냅니다!" />
      <button onClick={onClickButton}>버튼</button>
      {/* 아래에 카운트 변수 추가 */}
      <p>{num}</p>
    </>
  );
};

export default App;

반응형

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

typescript  (0) 2023.09.06
메모이제이션  (0) 2023.09.02
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
map, filter  (0) 2023.08.31
리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
반응형

# TODO

아래 버튼을 클릭하면 문구가 확인하기 -> 확인됨으로 바뀌게 하고

버튼 상태를 비활성화 시켜보자.

 

#1 버튼의 상태를 변경할 변수값 선언

 

 // TODO: 변수정의
    let [isConfirmed, setIsConfirmed] = useState(false);

#2 버튼을 누르면 문구변경 / 상태변경 함수 정의

 

// TODO: 함수정의
    const handleConfirm = () => {
        setIsConfirmed(true);
     }

#3 문구부분을 삼항 연산자를 사용하여 변경

 

return (
    <div>
        <button onClick={handleConfirm}
                disabled={isConfirmed}
        >
            {
                (isConfirmed === true)? "확인됨" : "확인하기"  // button의 문구부분 -> 삼항연산자 사용
            }
        </button>
    </div>
  )

반응형

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

메모이제이션  (0) 2023.09.02
State(useState)  (0) 2023.08.31
map, filter  (0) 2023.08.31
리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
CSS 적용  (0) 2023.08.30
반응형

기존 for문


기존 배열을 정의하고 for 문을 사용하여 출력할 수 있습니다.

const numArr = [1, 2, 3, 4];

// for문을 이용한 배열 처리

for(let i = 0; i < numArr.length; i++){
    console.log(numArr[i]);
}
 
[출력결과]
// 1
// 2
// 3
// 4

 

 

map 함수 이용


1) 배열 정의

const numArr = [1, 2, 3, 4];

// 배열.map()을 이용

const numArr2 = numArr.map();

// 배열.map(함수) 이용

const numArr2 = numArr.map(()=>{});

.map( ) 괄호 안에 함수를 입력합니다.

함수는 임의의 이름을 붙인 인수를 받을 수 있고 거기에 배열의 값이 들어갑니다. 그리고 반환하는 요소를 함수안에서 return 합니다.

 

const numArr = [1, 2, 3, 4];
// 인수 num에 배열의 값이 저장되고 return 으로 반환
const numArr2 = numArr.map((num)=>{
    return num;
});

console.log(numArr2); // [1, 2, 3, 4]

이 상태는 numArr2에 numArr을 그대로 저장한 것이나 다름 없으므로 맨 위의 for 문과 같이 수정해줍니다.

 

const numArr = [1, 2, 3, 4];

const numArr2 = numArr.map( num => console.log(num) );

[결과]

 

 

filter 함수


map 함수와 비슷한 filter 함수에 대해 알아봅시다.

filter 함수는 map 함수의 이용방법과 거의 동일하지만 return 뒤에 조건식이 들어가는 것에서 차이가 납니다.

다음 코드는 배열에서 홀수만 출력하는 예입니다.

 

// 배열 정의
const numArr = [1, 2, 3, 4, 5, 6];

// 홀수만 추출
// 2로 나누어 나머지가 1이면 홀수!
const newNumber = numArr.filter((num) => {
    return num % 2 === 1;
})

console.log(newNumber); // [1, 3, 5]

 

index 다루어보기


반복문을 사용해 배열을 처리할 때 몇 번째 요소인지 알아야하는 경우가 생깁니다.

for문을 사용하면 애초에 index 값을 이용하기 때문에 순서에 대한 개념을 이용할 수 있습니다.

// 배열 정의

const nameArr = ["철수", "영희", "민수"];

// for 문을 사용한 index 이용
for(let index = 0; index < nameArr.length; index++){
    console.log(`${index + 1} 번째 사람의 이름은 ${nameArr[index]} 입니다.`)
}

 

같은 코드를 map 함수를 이용해 처리해봅시다.

// 배열 정의

const nameArr = ["철수", "영희", "민수"];

// map 함수 이용

let newArr = nameArr.map((name, index)=>{console.log(`${index + 1} 번째 사람의 이름은 ${name} 입니다.`)});

 

map 함수를 이용한 활용예


이름이 철수, 영희, 민수 라는 배열이 선언되어있고, 철수 이름 뒤에는 님이라는 존칭이 붙은 새로운 배열을 생성해보자.
// 배열 정의

const nameArr = ["철수", "영희", "민수"];

// map 함수 이용

let newNameArray = nameArr.map((name) => {
    if(name === "철수") {
        return `${name}님`;
    } else {
        return name;
    }
})

console.log(newNameArray);

반응형

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

State(useState)  (0) 2023.08.31
리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
CSS 적용  (0) 2023.08.30
JSX 문법  (0) 2023.08.30
반응형

// A_Lifecycle.js : 자식 컴포넌트
// 컴포넌트 단축키 : rfce
// TODO: 리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정
import React from 'react'
import { useEffect, useState } from 'react';

// 컴포넌트 : 함수 컴포넌트(클래스 컴포넌트(과거))
// es6 : ECMAscript == 모던자바스크립트
function A_Lifecycle() {
    // 변수와 함수를 정의하는 부분
    // TODO: 변수 정의 : 바인딩 함수
    // TODO: 사용법 : let [변수명, set변수명] = useState("초기값");
    // TODO: set변수명() : 수정함수(setter 함수)
    let [element, setElement] = useState(true);

    // TODO: 함수정의
    // TODO: 컴포넌트 생성 함수 : 자동 실행
    // TODO: 화면이 뜨자마자 실행됨 : Mount 함수
    useEffect(()=>{
        // 최초 1번만 화면이 뜰때 실행됨
        console.log("mount Call");
    }, []);

    // TODO: 컴포넌트 수정함수 : 자동실행
    // TODO: 변수의 값이 바뀔 때 자동실행됨
    useEffect(()=>{
      // 최초 1번만 화면이 뜰때 실행됨
      console.log("update Call : " + element);
    }, [element]);  // [element] => 감시 할 변수명


    // 화살표 함수 생성 단축어 nfn
    // 클릭 함수
    const handleClick = () => {
      // element = true -> false (값 수정)
      setElement(false);
     }
   
  return (
    // 이러한 구조로 작성 : <div>HTML 태그들...</div>
    // 잘못된 구조 : <div>태그1</div><div>태그2</div>
    <div>
        <h2>This is Lifecycle</h2>
        <button onClick={handleClick}>클릭하세요</button>
    </div>
  )
}

export default A_Lifecycle

반응형

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

리액트의 조건문 : 삼항연산자를 사용한 예제  (0) 2023.08.31
map, filter  (0) 2023.08.31
CSS 적용  (0) 2023.08.30
JSX 문법  (0) 2023.08.30
Props  (0) 2023.08.30
반응형

React에서 CSS 적용은 어떻게 할까?


1. 우선 자식 컴포넌트를 생성해줍니다.

2. 자식 컴포넌트 이름과 똑같은 css 파일을 따로 생성해줍니다.

3. css 파일을 자식 컴포넌트에 import 시켜줍니다.

// D_ImportComp.js : 자식컴포넌트
// TODO: 리액트 컴포넌트 디자인 적용하기 : css 파일 적용
// TODO: 1) css 파일 준비해서 import 하면 적용됨
// TODO: 프로젝트가 커질수록 디자인 클래스선택자들이 중첩될 수 있음
// TODO: 예) A 사람 css : .alpha, B 사람 css : .alpha,
//                  p : 노란색        p : 파란색
// TODO: 2) 공통 디자인 적용 : 태그선택자 등을 자유롭게 코딩
// TODO: 3) 클래스/id 선택자로 디자인 함 : 프로젝트명(dms01-클래스명 ~ dms05-클래스명)


// rfce

import React from 'react'
// css 파일을 만들어서 import
// import "css 파일경로";
import "../assets/D_ImportComp.css";

function D_ImportComp() {
    // 변수나 함수 선언하는 곳

   
   
    // TODO: 화면에 보이는 부분
    return (
    <div>
        {/* CSS 클래스 :class="" // 리액트 => className="" */}
        <h2 className="dms01-h2">ImportComp</h2>
    </div>
  )
}

export default D_ImportComp
/* D_ImportComp.css */
.dms01-h2 {
    color: white;
    background-color: black;
}

반응형

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

map, filter  (0) 2023.08.31
리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
JSX 문법  (0) 2023.08.30
Props  (0) 2023.08.30
화면 출력  (0) 2023.08.30
반응형

JSX는 편리한 문법이지만 올바르게 사용하기 위해 규칙을 따라야 합니다.

요소는 감싸져 있어야 한다.


컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 합니다.

지난번 hello-react 프로젝트의 src 폴더 안 App.js 파일을 열어보겠습니다.

function App() {
  return (
   
      <h1>Hello React!!</h1>
      <h2>안녕하세요 주녘입니다.</h2>
   
  );
}

export default App;

이러한 형태의 코드는 작동하지 않습니다. 터미널을 열어 웹 브라우저에서 확인해 볼까요?

 

이러한 오류는 요소들이 부모 요소 하나에 의하여 감싸져 있지 않기 때문에 오류가 발생한 것입니다.

이러한 오류 수정은 아래 코드와 같이 작성하면 해결됩니다.

 

function App() {
  return (
    <div>
      <h1>Hello React!!</h1>
      <h2>안녕하세요 주녘입니다.</h2>
    </div>
  );
}

export default App;

요소사이에 <div></div> 태그로 감싸주면 오류가 해결됩니다.

중요한 JSX 규칙 중 하나는 return 이후에는 한 개의 태그로 둘러싸여 있어야 한다는 것입니다.

 

또는 리액트에서 제공하는 Fragment를 사용할 수 있습니다. Fragment는 두 가지 방법으로 사용가능합니다.

 

react에서 Fragment를 import 해서 사용하거나 빈 태그로 감싸면 됩니다.

 

import { Fragment } from "react";
function App() {
  return (
    <fragment>
      <h1>Hello React!!</h1>
      <h2>안녕하세요 주녘입니다.</h2>
    </fragment>
  );
}

 

export default App;
 

 

function App() {
  return (
    < >
      <h1>Hello React!!</h1>
      <h2>안녕하세요 주녘입니다.</h2>
    </ >
  );
}

 

export default App;

 

 

JSX에서의 JS표현


JSX 안에서 자바스크립트 표현식을 사용할 수 있습니다. JSX 내부에서 코드를 {   }로 감싸면 됩니다.

 

function App() {
  // 변수와 함수를 선언하는 곳
  const name = "주녘";
 
  return (
    <div>
      <h1>Hello {name}!!</h1>
      <h2>안녕하세요 {name}입니다.</h2>
    </div>
  );
}

export default App;

 

JSX에서 if문을 쓰고 싶다면? - 조건부 연산자를 활용!


JSX 내부에서 자바스크립트 표현식에서 if문을 사용할 수 없습니다.

if문을 사용하기 위해서는 JSX 밖에서 if문을 사용하여 값을 미리 설정하거나 JSX 내부에서 { } 안에 조건부 연산자를 사용하면 됩니다. 우리가 알고있는 삼항 연산자를 생각하면 됩니다.

 

function App() {
  // 변수와 함수를 선언하는 곳
  const name = "주녘";

  return (
    <div>
      {name === "주녘" ? <h1>주녘입니다.</h1> : <h2>주녘이가 아닙니다.</h2>}
    </div>
  );
}

export default App;

위와 같이 실행하면 결과화면이 주녘입니다. 라고 뜨겠죠?

만약 name의 값이 주녘이 아닌 철수이면 어떻게 될까요? 값을 변경해봅시다.

 

function App() {
  // 변수와 함수를 선언하는 곳
  const name = "철수";

  return (
    <div>
      {name === "주녘" ? <h1>주녘입니다.</h1> : <h2>주녘이가 아닙니다.</h2>}
    </div>
  );
}

export default App;

반응형

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

리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
CSS 적용  (0) 2023.08.30
Props  (0) 2023.08.30
화면 출력  (0) 2023.08.30
Hello! React  (0) 2023.08.30
반응형

props?


props는 "properties"를 줄인 표현어로 컴포넌트 속성을 설정할 때 사용하는 요소라고 합니다.

props 값은 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정할 수 있습니다.

 

 

JXS에서 props 렌더링


우선 MyComponent 컴포넌트를 수정하여 해당 컴포넌트에서 name 이라는 props를 렌더링하도록 설정해봅시다.

function MyComponent(props) {
  return (
    <div>
        안녕하세요, 저는 {props.name} 입니다.
    </div>
  )
}

export default MyComponent

 

부모 컴포넌트에서 props값 지정하기


부모 컴포넌트인 App.js 에서 MyComponent의 props 값을 지정해봅시다.

import "./App.css";
import MyComponent from "./pages/MyComponent";

function App() {
 
  return (
    <div>
      <MyComponent name="주녘"></MyComponent>      // name ="주녘" 을 추가하였습니다.
    </div>
  );
}

export default App;

 

 

props 기본값 설정 : defaultProps


부모 컴포넌트에서 작성한 name 값을 지우고 저장해봅시다.

현재 name에 값을 지정하지 않았기 때문에 안녕하세요, 저는 입니다. 라고 보이게 됩니다.

이처럼 props 값을 따로 지정하지 않았을 때 보여 줄 기본값을 설정하는 defalutProps을 알아봅시다.

 

// MyComponent.js
import React from 'react'

const MyComponent = props => {
    return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>
}

MyComponent.defaultProps = {
    name: '기본이름'
};

export default MyComponent

 

 

태그 사이의 내용을 보여주는 children


리액트 컴포넌트를 사용할 때 컴포넌트 태그 사이의 내용을 보여주는 props가 있습니다.

바로 children 입니다.

부모 컴포넌트인 App.js 파일을 수정해봅시다.

import "./App.css";
import MyComponent from "./pages/MyComponent";

function App() {
 
  return (
    <div>
      <MyComponent>리액트</MyComponent>
    </div>
  );
}

export default App;

위의 코드에서 <MyComponent>리액트</MyComponent태그 사이에 작성한 "리액트"라는 문자열을 MyComponent 내부에서 보여주려면 props.children 값을 보여주어야 합니다.

자식 컴포넌트인 MyComponent.js를 수정해봅시다

// MyComponent.js
import React from 'react'

const MyComponent = props => {
    return <div>
        안녕하세요, 제 이름은 {props.name}입니다.
        children 값은  {props.children} 입니다.
    </div>
}

MyComponent.defaultProps = {
    name: '기본이름'
};

export default MyComponent

 

비구조화 할당 문법을 사용하여 props 내부 값 추출해보기


props 값을 조회할 때마다 props.name, props.children과 같이 props. 이라는 키워드를 앞에 붙여 사용하고 있습니다.

조금더 편리하게 사용하기 위해 비구조화 문법을 사용하여 내부 값을 바로 추출하는 방법을 알아보겠습니다. 😊

 

// MyComponent.js
import React from 'react'

const MyComponent = props => {
    const {name, children} = props;
    return <div>
        안녕하세요, 제 이름은 {name}입니다.
        children 값은  {children} 입니다.
    </div>
}

MyComponent.defaultProps = {
    name: '기본이름'
};

export default MyComponent
// MyComponent.js
import React from 'react'

const MyComponent = ({name, children}) => {
    return <div>
        안녕하세요, 제 이름은 {name}입니다.
        children 값은  {children} 입니다.
    </div>
}

MyComponent.defaultProps = {
    name: '기본이름'
};

export default MyComponent

조금 더 간단해진것을 볼 수 있습니다.

 

propTypes를 통한 props 검증


컴포넌트의 필수 props를 지정하거나 props의 타입을 지정할 때는 propTypes를 사용합니다.

컴포넌트의 propTypes를 지정하는 방법은 위 쪽의 defaultProp을 설정하는 것과 비슷합니다.

propTypes 를 사용하기 위해서는 상단에 import 구문을 사용하여 불러와야 합니다.

// MyComponent.js

import PropType from 'prop-types';  // PropType import
 
const MyComponent = ({ name, children }) => {
  return (
  (... 이하생략)
  );
};

MyComponent.defaultProps = {
    name: "기본이름"
}

MyComponent.propType = {
    name:PropType.string               // name 값을 문자열 형태로만 전달해야함!
}

export default MyComponent;

이런식으로 설정을 해주면 name 값은 무조건 문자열(string) 형태로 전달해야 된다는 것을 의미합니다.

App.js에서 name이 문자열이 아닌 다른 값으로 전달한다면 어떻게 될까요?

 

import './App.css';
import MyComponent from './pages/MyComponent';

const App = () => {
  return <MyComponent name={10}>리액트</MyComponent>    // name 값을 숫자 10으로 전달해보았습니다.
}

MyComponent.defaultProps = {
  name: "기본이름"
};

export default App;

값은 나타나기는 했지만, 콘솔에 경고창이 뜨는 것을 확인할 수 있습니다.

오류 메시지를 확인했으면 name 값을 제대로 설정해주시면 됩니다.

 

isRequired를 사용하여 필수 propTypes 설정


propTypes를 지정하지 않았을 때 경고메시지를 띄워주는 작업을 해봅시다.

propTypes를 지정할 때 뒤에 isRequired를 붙여주면 끝입니다!

favoriteFruit 라는 문자열을 필수 props로 지정해보겠습니다.

// MyComponent.js

import PropTypes from 'prop-types';


const MyComponent = ({ name, favoriteFruit, children }) => {  // favoriteFruit 추가
  return (
    <div>
      안녕하세요, 제 이름은 {name}입니다.
      <br />
      children 값은 {children}
      입니다.
      <br/>
      제가 좋아하는 과일은 {favoriteFruit}입니다. 
    </div>
  );
};

MyComponent.defaultProps = {
    name: "기본이름"
}

MyComponent.propTypes = {
    name: PropTypes.string,
    favoriteFruit: PropTypes.string.isRequired   // 문자열 입력받게
};

export default MyComponent;

만약 favoriteFruit 를 지정하지 않았으면 어떻게 될까요?

favoriteFruit proptype를 입력하라고 경고창이 뜨는 것을 볼 수 있습니다. 

반응형

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

리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
CSS 적용  (0) 2023.08.30
JSX 문법  (0) 2023.08.30
화면 출력  (0) 2023.08.30
Hello! React  (0) 2023.08.30
반응형

들어가기 전에


컴포넌트 파일에서 웹브라우저 화면에 표시되는 영역은 함수의 return 값 아래 부분에 작성해주어야 화면에 정상적으로 출력이 됩니다.

function Home() {

  // TODO: 변수를 정의하는 곳 : 여기
  let array = ["a", "b", "c"];  // 일반 변수
  // 리액트 특징 : 변수값 + html 태그를 같이 사용이 가능함(JSX 표현식)
  let input = <b>문자열 출력되나요?</b>;

  // TODO: 함수를 정의하는 곳 : 여기
  // 함수선언식 : function 함수명() {}
  // 함수표현식 : let 함수명 function (){};
  // 화살표함수 : let 함수명 () => {}
  // 화살표함수 단축키 : nfn
 
  const testFunc = () => {
    return "함수입니다";
  }

  // 클릭이벤트 함수
  const myClick = () => {
    alert("클릭했어요");
   }

  // TODO: HTML 태그 + JSX 표현식{} : return 안에 코딩함
  // TODO: return : 웹브라우저 화면에 표시되는 영역
  return (
<div>
   .....이곳에 작성!
 </div>
  )
}

export default Home

화면에 출력이 가능한 것들


      {/* TODO: 문자열 출력 : OK  */}
      {/* 사용법 : {"문자열"} */}
      {"문자열 출력되나요!!!"}
      <br/>
      {/* TODO: 변수에 저장된 html태그 + 문자열 출력 : OK */}
      {/* 사용법 : {변수명} */}
      {input}
      <br/>
      {/* TODO: html 태그 : OK */}
      {<b>이것도 출력될까요?</b>}
      <br/>
      {/* TODO: 숫자출력 : OK */}
      {1}
      <br/>
      {1 * 2 + 3 - 2}
      <br/>

      {/* TODO: 문자열 붙이기 : + : OK */}
      {"abc" + "가나다"}
      <br/>

      {/* TODO: JSX 표현식 : {<태그>{문자열}</태그>} : OK */}
      {<b>{"안녕하세요"}</b>}
      <br/>

      {/* TODO: 배열 출력 : OK */}
      {["가", "나", "다"]}
      <br/>
      {[1,2,3]}
      <br/>
      {array}
      <br/>

      {/* TODO: 함수 출력 : OK */}
      {/* 함수의 사용 : 함수명() */}
      {testFunc() + " 이것도 될까요?"}
      <br/>

      {/* TODO: 3항 연산자 : 조건식(축약형) : OK */}
      {/* 사용법 : (조건식==true)? 참:거짓; */}
      {true? "true":"false"}
      <br/>
      {false? "true":"false"}
      <br/>

      {/* TODO: HTML 태그 속성의 값으로 {} 넣어보기 : OK  */}
      <a href={"http://www.naver.com"}>네이버</a>
      <br/>
      <button onClick={myClick}>클릭하세요</button>
      <br/>

      {/* TODO: 자바스크립트 내장함수 : OK */}
      {console.log("이것도 출력될까요?")}
      <br/>
      {/* 오늘 요일(1 ~ 7) new Date() */}
      {new Date().getDay()}
      <br/>
      {new Date().getFullYear() + "년"}
      <br/>
      {(new Date().getMonth()+1) + "월"}
      <br/>


화면에 출력하지 못하는 것들


아래의 내용들은 중괄호{ } 안에 입력하여도 화면에 출력이 안되며 오류가 발생합니다.

      {/* 화면에 출력 안되는 것 */}
      {/* ------------------------------------------------------ */}
      {/* TODO: boolean : 참/거짓 */}
      {/* 해결책 : 참/거짓을 문자열로 변경하여 출력 */}
      {true}
      <br/>

      {/* TODO: 객체 출력, 에러 발생*/}
      {/* 해결책 : 객체 -> 문자열로 변경해서 출력 */}
      {/* {{name:"홍길동", email:"hong@naver.com"}} */}
      <br/>

      {/* TODO: 조건문 if, 에러 발생 */}
      {/* 해결책 : 삼항연산자 사용 */}
      {/* {if(true){return "true"}} */}

      {/* TODO: 반복문 for, 에러 발생 */}
      {/* 해결책 : map() 함수 가능 */}
      {/* {for(let i = 1; i<2 i++){console.log("aaaa")}} */}
반응형

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

리액트 컴포넌트의 생명주기(LifeCycle) : 생성/수정  (0) 2023.08.30
CSS 적용  (0) 2023.08.30
JSX 문법  (0) 2023.08.30
Props  (0) 2023.08.30
Hello! React  (0) 2023.08.30

+ Recent posts