본문 바로가기

Front-end/필기일지

230927 [React] 리액트 React 문법(JSX) / 리액트 엘리먼트 React element / 컴포넌트 Component / 리액트에서의 event

반응형

[23.09.27] 42일차

 

<<진도>>

Front-end

- 리액트 React 문법(JSX)

- 리액트 엘리먼트 React element

- 컴포넌트 Component

- 리액트에서의 event

 

<<오늘의 팁>>

- 확장 ‘Errorlens’

syntax에러나 오류 시 알림보여줌

 

- HTML 태그 내 js영역 {} 주석 가능형태

    const favorites = (

      <ul class="favorites">

        {

          // hi

        }

        {

          /* test('수요일') */

        }

        {/* 100 + 5 */}

      </ul>

    );

 

- React에서는 ‘class’가 다른 기능적 의미를 가지고있기 때문에 태그의 class

“className”으로 표기해야한다. (but, 렌더링 시엔 ‘class’ 로 나온다)

ex) <div class=“class”> X => <div className=“className”> O

 

기본

 

* ex01-javascript // 순수 자바스크립트 형태

<body>

  <h1>상품 1페이지</h1>

  <form action="">

    <input type="text" name="name" placeholder="상품명을 입력하세요">

    <button type="submit">추가</button>

  </form>

  <div class="main-card">

    <img src="img/food-one.jpg" alt="올리브 오일" width="400">

    <button></button>

  </div>

  <ul class="favorites">

    <li>

      <img src="img/food-one.jpg" alt="음식">

    </li>

    <li>

      <img src="img/food-two.jpg" alt="음식">

    </li>

    <li>

      <img src="img/food-three.jpg" alt="음식">

    </li>

  </ul>

  <!-- script -->

  <script>

    // 1. 하트 버튼 엘리먼트 접근

    const heartButton = document.querySelector('.main-card button');

 

    // 2. 하트 버튼 클릭하면, 이미지 추가(li > img)

    heartButton.addEventListener('click', () => {

      // 3. 하트 색 변경

      heartButton.innerText = '💜';

 

      // 4. li 엘리먼트생성

      const li = document.createElement('li');

      // 5. img 엘리먼트생성

      const img = document.createElement('img');

      img.src = "img/food-one.jpg"; // img src 접근

      console.log('img :', img);

 

      // 6. li 자식으로 img 추가 (li > img)

      li.appendChild(img);

      console.log('li :', li);

 

      // 7. ul 엘리먼트 접근 : li가 추가될 엘리먼트

      const favorites = document.querySelector('ul.favorites')

      // 8. ul li추가

      favorites.appendChild(li);

 

    });

  </script>

 

 

[리액트 React]

공식홈페이지: https://ko.legacy.reactjs.org/

 

[리액트 라이브러리 연결] JavaScript에서 사용하기 사전단계

<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>

  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

 

작업하는 script위에 넣어줘야한다

 

  <script type = "text/babel">

** Babel : 웹브라우저 js가 처리하지 못하는 형태 언어를 변환하여 처리해주는 역할

    const foodItem = (

      <li>

        <img src="img/food-one.jpg" alt="음식" />

      </li>

    );

형태를

 

[JSX]

JS: JavaScript / X: Xml

    [react] JSX =================================================

    : JavaScript + XML(html같은 마크업 랭귀지)

    : JavaScript내에 HTML 작성 가능

    : HTML 태그 내 JavaScript 작성하려면, {} 사용

    : 작성된 HTML '리액트 엘리먼트'라고 한다.

    =============================================================

 

ReactDOM :

const root = ReactDOM.createRoot(domContainer);
root.render(e(LikeButton));

웹브라우저가 렌더할때의 DOM이 아닌 react실행시 복사된 가상DOM

 

* ex02-react-JSX

<body>

  <div id="food-li-insert"></div>

 

  <!-- React를 실행. -->

  <!-- 주의: 사이트를 배포할 때는 "development.js" "production.min.js"로 대체하세요. -->

  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>

  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

 

  <script type="text/babel"> // babel : js에서 html태그를 인식하게 하기위한

    /*

    [react] JSX =================================================

    : JavaScript + XML(html같은 마크업)

    : JavaScript내에 HTML 작성 가능

    : HTML 태그 내 JavaScript 작성하려면, {} 사용

    : 작성된 HTML '리액트 엘리먼트'라고 한다.

    =============================================================

    */

    console.log('처음 배우는 리액트');

 

    const foodItem = (

      <li>

        <img src="img/food-one.jpg" alt="음식" />

      </li>

    );

    // [React문법] JSX에서는 닫는 태그 표시가 필수 닫는 태그가없다면 끝나는 의미로 '/'가 들어간다.

 

    const hi = '오늘도 좋은 하루';

    function test(args) {

      return `인수는 ${args}입니다.`;

    }

 

    const title = (

      <h1>상품 1페이지</h1>

    );

 

    const mainCard = (

      <div class="main-card">

        <img src="img/food-one.jpg" alt="올리브 오일" width="400" />

        <button></button>

      </div>

    );

 

    const form = (

      <form action="">

        <input type="text" name="name" placeholder="상품명을 입력하세요" />

        <button type="submit">추가</button>

      </form>

    );

 

    const favorites = (

      <ul class="favorites">

        {foodItem}

        {foodItem}

        {foodItem}

      </ul>

    );

 

    // 다수 리액트 엘리먼트를 렌더링 할 때 app으로 묶어서 렌더

    const app = (

      // 다수의 element를 처리하기 위해서는 묶어주는 부모요소가 필요

      <div>

        {title}

        {mainCard}

        {form}

        {favorites}

      </div>

    );

 

    // 리액트 엘리먼트가 추가될 위치

    const foodListInsert = document.querySelector('#food-li-insert');

 

    // 리액트를 이용하여 엘리먼트 추가

 

    // [ver.17까지의 형태]

    // ReactDOM.render(리액트엘리먼트, 엘리먼트);

    // ReactDOM.render(foodItem, foodListInsert);

 

    // [ver.18]

    // ReactDOM.createRoot(엘리먼트).render(리액트엘리먼트);

    // ReactDOM.createRoot(foodListInsert).render(foodItem);

    ReactDOM.createRoot(foodListInsert).render(app);

    // .render()메서드는 하나만 가능

 

    // 각각 변수에 저장된 엘리먼트들의 렌더링을 한번에 하고싶을 때는 묶어서 렌더

  </script>

 

* ex02-react-JSX-clean

[JavaScript html 태그를 넣어 렌더하는 JSX문법]

<body>

  <div id="food-li-insert"></div>

 

  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>

  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

 

  <script type="text/babel">

    const title = <h1>상품 1페이지</h1>;

   

    const form = (

      <form action="">

        <input type="text" name="name" placeholder="상품명을 입력하세요" />

        <button type="submit">추가</button>

      </form>

    );

 

    const mainCard = (

      <div class="main-card">

        <img src="img/food-one.jpg" alt="올리브 오일" width="400" />

        <button></button>

      </div>

    );

 

    const foodItem = (

      <li>

        <img src="img/food-one.jpg" alt="음식" />

      </li>

    );

 

    const favorites = (

      <ul class="favorites">

        {foodItem}

        {foodItem}

        {foodItem}

      </ul>

    );

 

    // 여러 리액트 엘리먼트를 렌더링하고자 할 때 묶어주기

    const app = (

      <div>

        {title}

        {form}

        {mainCard}

        {favorites}

      </div>

    );

 

    // 리액트 엘리먼트가 추가될 위치

    const foodListInsert = document.querySelector('#food-li-insert');

 

    // 리액트를 이용하여 엘리먼트 추가

    ReactDOM.createRoot(foodListInsert).render(app);

  </script>

 

 

* ex03-react-component-ex

컴포넌트 연습

 <div id="text"></div>

  <hr>

 

  <script type="text/babel">

    // 1. 리액트 엘리먼트를 변수에 저장 --------------------------------

    const h1 = <h1>안녕하세요</h1>;

 

    const one = 100;

 

    const ul = (

      // [react element] ==========================

      // {one} // html 영역이 아닌곳에서 {}Error

      // console.log(); //리액트 element가 오는데 js 문법도 Error

      <ul>

        <li>첫 번째</li>

        <li>두 번째</li>

      </ul>

    );

 

    const app = (

      <div>

        {h1}

        {ul}

      </div>

    );

 

    // 2. 컴포넌트 생성 ------------------------------------------------

    /*

    [문법] ======================================================

    // 컴포넌트를 생성하는것은 함수 정의와 같음.

    // but, 이름은 대문자로 시작!

   

    function 대문자시작(props) { // props = properties(속성들)

      // 명령어;

      // 어떤 코드가 오든 마지막엔 React element

      return (리액트 엘리먼트);

    }

    =============================================================

    */

 

    const userName = '홍길동';

 

    function H1({ name, age }) { // 대문자 시작 중요(강제)

      // console.log('props : ', props);

      console.log(name, age);

      // props Object 객체 형태

      return (

        <div>

          <h1>안녕하세요, {name}!</h1>

          <div>나이는 {age}세 입니다.</div>

        </div>

      );

    }

    // 익명 함수 / 화살표 함수 형태도 컴넌트명은 무조건 대문자로 시작

    const Ul = () => {

      return (

        <ul>

          <li>첫 번째</li>

          <li>두 번째</li>

        </ul>

      );

    };

 

    const componentApp = (

      // 컴포넌트는 리액트 엘리먼트 태그형태로 쓴다.

      // 하나만 들어가도 부모필요

      <div>

        <H1 name="박보검" age="25" />

        <H1 name={userName} age="35"></H1>

        {H1({ name: '이미자', age: 52 })}

        <Ul />

      </div>

    );

 

    const ComponentApp = () => {

      console.log('== [ 컴포넌트 앱 ] ==');

      return (

        <div>

          <H1 name="박보검" age="25" />

          <H1 name={userName} age="35"></H1>

          {H1({ name: '이미자', age: 52 })}

          <Ul />

        </div>

      );

    }

 

    const insert = document.getElementById('text');

    // ReactDOM.createRoot(insert).render(app);  

    // ReactDOM.createRoot(insert).render(componentApp);  

    ReactDOM.createRoot(insert).render(<ComponentApp />);  

  </script>

 

* ex03-react-component

  <div id="food-li-insert"></div>

 

  <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>

  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>

  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

 

  <script type="text/babel">

    // /react element/

    // const title = <h1>상품 1페이지</h1>;

 

    // * component (이름있는 함수 선언식 정의)

    function Title(props) {

      // return <h1>상품 1페이지</h1>;

      return <h1>{props.children}</h1>;

      {/* content(페이지1)는 상위 props의 자식(children)으로 받아준다 */ }

    }

 

    // /react element/

    // const form = (

    //   <form action="">

    //     <input type="text" name="name" placeholder="상품명을 입력하세요" />

    //     <button type="submit">추가</button>

    //   </form>

    // );

 

    // * component (익명함수)

    const Form = function () {

      return (

        <form action="">

          <input type="text" name="name" placeholder="상품명을 입력하세요" />

          <button type="submit">추가</button>

        </form>

      );

    }

 

    // /react element/

    // const mainCard = (

    //   <div class="main-card">

    //     <img src="img/food-one.jpg" alt="올리브 오일" width="400" />

    //     <button></button>

    //   </div>

    // );

 

    // * component (화살표 함수)

    const MainCard = ({ src }) => {

      function heartClick() {

        console.log('하트버튼 클릭!!!');

      }

 

      return (

        <div class="main-card">

          <img

            src={src}

            alt="올리브 오일"

            width="400"

            // CSS 추가

            style={{ border: "1px solid #f00", }}

          // 외부{}=<태그>내에서 css/js표현식

          // 내부{}=객체표시

          />

          <button onClick={heartClick}></button>

        </div>

      );

    }

 

    // /react element/

    // const foodItem = (

    //   <li>

    //     <img src="img/food-one.jpg" alt="음식" />

    //   </li>

    // );

 

    // * component

    const FoodItem = ({ src }) => {

      // console.log('FoodItem props', props);

      return (

        <li>

          <img src={src} alt="음식" />

        </li>

      );

    };

 

    // react element

    // const favorites = (

    //   <ul class="favorites">

    //     {foodItem}

    //     {foodItegm}

    //     {foodItem}

    //   </ul>

    // );

 

    // * component

    const Favorites = () => {

      return (

        <ul class="favorites">

          <FoodItem src="img/food-one.jpg" />

          <FoodItem src="img/food-two.jpg" />

          <FoodItem src="img/food-three.jpg" />

        </ul>

      );

    };

 

    // 여러 리액트 엘리먼트를 렌더링하고자 할 때 묶어주기

    const app = (

      <div>

        {/* title */}

        <Title>페이지 1</Title>

        {/* content(페이지1)는 상위 props의 자식(children)으로 받아준다 */}

        {/* form */}

        <Form />

        {/* mainCard */}

        <MainCard src="img/food-one.jpg" />

        {/* foodItem */}

        <Favorites />

      </div>

    );

 

    // 리액트 엘리먼트가 추가될 위치

    const foodListInsert = document.querySelector('#food-li-insert');

 

    // 리액트를 이용하여 엘리먼트 추가

    ReactDOM.createRoot(foodListInsert).render(app);

  </script>

 

* ex03-react-component-clean

<script type="text/babel">

    // * component

    function Title(props) {

      return <h1>{props.children}</h1>;

    }

 

    // * component

    const Form = function () {

      return (

        <form action="">

          <input type="text" name="name" placeholder="상품명을 입력하세요" />

          <button type="submit">추가</button>

        </form>

      );

    }

 

    // * component

    const MainCard = ({ src }) => {

      function heartClick() {

        console.log('하트버튼 클릭!!!');

      }

 

      return (

        <div class="main-card">

          <img

            src={src}

            alt="올리브 오일"

            width="400"

            // CSS 추가

            style={{ border: "1px solid #f00", }}

          />

          <button onClick={heartClick}></button>

        </div>

      );

    }

 

    // * component

    const FoodItem = ({ src }) => {

      return (

        <li>

          <img src={src} alt="음식" />

        </li>

      );

    };

 

    // * component

    const Favorites = () => {

      return (

        <ul class="favorites">

          <FoodItem src="img/food-one.jpg" />

          <FoodItem src="img/food-two.jpg" />

          <FoodItem src="img/food-three.jpg" />

        </ul>

      );

    };

 

    // 여러 리액트 엘리먼트를 렌더링하고자 할 때 묶어주기

    const app = (

      <div>

        <Title>페이지 1</Title>

        {/* content(페이지1)는 상위 props의 자식(children)으로 받아준다 */}

        <Form />

        <MainCard src="img/food-one.jpg" />

        <Favorites />

      </div>

    );

 

    // 리액트 엘리먼트가 추가될 위치

    const foodListInsert = document.querySelector('#food-li-insert');

 

    // 리액트를 이용하여 엘리먼트 추가

    ReactDOM.createRoot(foodListInsert).render(app);

  </script>

 

* ex04-react-event

<script type="text/babel">

    // * component

    function Title(props) {

      return <h1>{props.children}</h1>;

    }

 

    // * component

    const Form = () => { // 화살표함수로 component만들면 {}, return 생략가능

 

      // handler + Form + Submit

      function handlerFormSubmit(event) {

        console.log('추가버튼 클릭함!!');

        // refresh 방지

        event.preventDefault();

      }

 

      return (

        <form action="" onSubmit={handlerFormSubmit}>

          <input type="text" name="name" placeholder="상품명을 입력하세요" />

          <button type="submit">추가</button>

        </form>

      );

    };

 

    // * component

    const MainCard = ({ src }) => {

      function heartClick() {

        console.log('하트버튼 클릭!!!');

      }

 

      return (

        <div className="main-card">

          <img

            src={src}

            alt="올리브 오일"

            width="400"

            // CSS 추가

            style={{ border: "1px solid #f00", }}

          />

          <button onClick={heartClick}></button>

        </div>

      );

    }

 

    // * component

    const FoodItem = ({ src }) => {

      return (

        <li>

          <img

            src={src}

            alt="음식"

            // css 추가

            style={{

              width: "150px",

              height: "100px",

              backgroundSize: "contain",

            }}

          />

        </li>

      );

    };

 

    // * component

    const Favorites = () => {

      return (

        <ul className="favorites">

          <FoodItem src="img/food-one.jpg" />

          <FoodItem src="img/food-two.jpg" />

          <FoodItem src="img/food-three.jpg" />

        </ul>

      );

    };

 

    // 여러 리액트 엘리먼트를 렌더링하고자 할 때 묶어주기

    const app = (

      <div>

        <Title>페이지 1</Title>

        {/* content(페이지1)는 상위 props의 자식(children)으로 받아준다 */}

        <Form />

        <MainCard src="img/food-one.jpg" />

        <Favorites />

      </div>

    );

 

    // 리액트 엘리먼트가 추가될 위치

    const foodListInsert = document.querySelector('#food-li-insert');

 

    // 리액트를 이용하여 엘리먼트 추가

    ReactDOM.createRoot(foodListInsert).render(app);

  </script>

 

 

 

반응형