개발/React

React - React.js (JSX, State, Props)

잇(IT) 2023. 9. 15. 01:18
728x90
- JSX

- JSX는 JavaScript 파일 내에 HTML과 유사한 마크업을 작성할 수 있게 해주는 JavaScript용 구문 확장이다.

 

- JSX의 규칙

1. 단일 루트 요소를 반환한다.

<div>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</div>

- 최상위 태그로 <div>를 사용하였고 <>를 사용해도 된다.

<>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</>

- <> 빈 태그를 조각이라고 한다. HTML 트리에 흔적을 남기지 않고 항목을 그룹화 할 수 있다.

 

2. 모든 태그는 닫아야 한다.

- 자체 닫는 태그인 <img> 같은 경우 <img />와 같이 닫는다.

 

3. CamelCase를 사용한다.

- 이름에는 대시를 포함하거나 class와 같은 예약어를 쓸 수 없다.

- class는 예약어이므로 React에서는 해당 DOM 속성의 className 이름을 따서 대신 작성한다.


- JSX 예시

 

- App.js

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img 
        src="https://i.imgur.com/yXOvdOSs.jpg" 
        alt="Hedy Lamarr" 
        className="photo" 
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve the spectrum technology</li>
      </ul>
    </>
  );
}

 

- HTML -> JSX로 변환하기

- App.js

export default function Bio() {
  return (
    <div class="intro">
      <h1>Welcome to my website!</h1>
    </div>
    <p class="summary">
      You can find my thoughts here.
      <br><br>
      <b>And <i>pictures</b></i> of scientists!
    </p>
  );
}

- App.js

export default function Bio() {
  return (
    <div>
      <div className="intro">
        <h1>Welcome to my website!</h1>
      </div>
      <p className="summary">
        You can find my thoughts here.
        <br /><br />
        <b>And <i>pictures</i></b> of scientists!
      </p>
    </div>
  );
}

- Props

- React 구성 요소는 props를 사용하여 서로 통신한다. 모든 상위 구성 요소는 하위 구성 요소에 일부 정보를 전달할 수 있다.

- Props는 HTML 속성을 상기시킬 수 있지만 이를 통해, 객체 배열 및 함수를 포함한 모든 JavaScript 값을 전달할 수 있다.

 

- App.js

function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/1bX5QH6.jpg"
      alt="Lin Lanying"
      width={100}
      height={100}
    />
  );
}

export default function Profile() {
  return (
    <Avatar />
  );
}

- 태그에 전달 할 수 있는 props는 미리 정의되어 있다. <Avatar />와 같이 전달하면 된다.

 

- props를 컴포넌트에 전달하는 방법

1. props를 하위 컴포넌트에 전달

export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  );
}

 

2. 하위 구성 요소 내부의 props 읽기

- function Avatar 함수 안에 ({ })에 props 요소를 ,로 구분하여 읽을 수 있다.

function Avatar({ person, size }) {
  // person and size are available here
}

- Avatar의 props를 렌더링하기위한 코드를 아래와 같이 작성할 수 있다.

 

- App.js

import { getImageUrl } from './utils.js';

function Avatar({ person, size }) {
  return (
    <img
      className="avatar"
      src={getImageUrl(person)}
      alt={person.name}
      width={size}
      height={size}
    />
  );
}

export default function Profile() {
  return (
    <div>
      <Avatar
        size={100}
        person={{ 
          name: 'Katsuko Saruhashi', 
          imageId: 'YfeOqp2'
        }}
      />
      <Avatar
        size={80}
        person={{
          name: 'Aklilu Lemma', 
          imageId: 'OKS67lh'
        }}
      />
      <Avatar
        size={50}
        person={{ 
          name: 'Lin Lanying',
          imageId: '1bX5QH6'
        }}
      />
    </div>
  );
}

 

- utils.js

export function getImageUrl(person, size = 's') {
  return (
    'https://i.imgur.com/' +
    person.imageId +
    size +
    '.jpg'
  );
}

 

- props를 사용하면 부모 및 자식 구성 요소를 독립적으로 생각할 수 있다.

- 내부 props를 어떻게 사용할지 생각할 필요 없이 내부 person props를 변경할 수 있다.

function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

 

- Props의 기본값 지정

- 값이 지정되지 않았을 때 prop에 기본값을 지정하려면 =를 통해 기본값을 넣어서 값을 넣으면 된다.

function Avatar({ person, size = 100 }) {
  // ...
}

- <Avatar person={} />의 값이 렌더링 되면 size=100으로 설정되어 렌더링 된다.

 

- JSX를 자식으로 전달

- 자신만의 구성 요소를 중첩하고 싶을 수도 있다.

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{
          name: "Katsuko Saruhashi",
          imageId: "YfeOqp2",
        }}
      />
    </Card>
  );
}

- 위와 같이 기본 태그가 아닌 개발자가 임의로 생성한 <Container>를 통해 태그들을 감싼 것을 볼 수 있다.

- JSX 태그 내에 콘텐츠를 중첩하면 상위 구성 요소는 children을 이용하여 해당 컨텐츠를 받는다.

 

import Avatar from "./Avatar.js";

function Card({ children }) {
  return (
    <div style={{ margin: 20, padding: 20, border: "1px solid gray" }}>
      {children}
    </div>
  );
}

export default function Profile() {
  return (
    <Card>
      <Avatar
        size={100}
        person={{
          name: "Katsuko Saruhashi",
          imageId: "YfeOqp2",
        }}
      />
    </Card>
  );
}

- {children}에 자식 요소들이 들어가게 된다.


- State

- 구성 요소는 상호 작용의 결과로 화면의 내용을 변경해야 하는 경우가 많다. 양식에 입력하면 입력 필드가 업데이트되고, 버튼 클릭을 하면 변경되고 ... 등

- React에서는 이러한 종류의 구성 요소별 메모리를 state라고 한다.

 

- App.js

import { sculptureList } from './data.js';

export default function Gallery() {
  let index = 0;

  function handleClick() {
    index = index + 1;
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

- data.js

export const sculptureList = [{
  name: 'Homenaje a la Neurocirugía',
  artist: 'Marta Colvin Andrade',
  description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.',
  url: 'https://i.imgur.com/Mx7dA2Y.jpg',
  alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.'  
}, .....

 

- 위 코드는 위와 같은 페이지를 생성하고, Next를 누르게 되면 다음 페이지로 넘어가도록 하고 싶지만 변경 사항을 바로 렌더링 시키는 코드가 없다.

 

1. 지역 변수를 렌더링 간에 유지되지 않는다.

2. 지역 변수를 변경해도 렌더링이 트리거되지 않는다.

 

- 새 데이터로 구성요소를 업데이트하려면 다음 두 가지 작업이 수행되어야 한다.

1. 렌더링 간에 데이터를 유지한다.

2. React를 트리거하여 새 데이터로 구성 요소를 렌더링한다.

 

- "useState"는 다음 두 가지를 제공한다.

1. 렌더링 간에 데이터를 유지하는 상태 변수이다.

2. 변수를 업데이트하고 React를 트리거하여 구성 요소를 다시 렌더링하는 state setter 함수이다.

 

- state 사용 방법

1. useState를 React에서 가져온다.

import { useState } from 'react';

2. 기존의 코드를 아래와 같이 변경한다.

let index = 0;

// 위 코드를 아래와 같이 변경한다.

const [index, setIndex] = useState(0);

 

-  index는 상태 변수고, setIndex는 setter 함수이다.

 

3. 아래 코드를 추가해준다.

function handleClick() {
  setIndex(index + 1);
}

 

- 변경된 최종 코드

 

- App.js

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i> 
        by {sculpture.artist}
      </h2>
      <h3>  
        ({index + 1} of {sculptureList.length})
      </h3>
      <img 
        src={sculpture.url} 
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

- data.js

export const sculptureList = [{
  name: 'Homenaje a la Neurocirugía',
  artist: 'Marta Colvin Andrade',
  description: 'Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.',
  url: 'https://i.imgur.com/Mx7dA2Y.jpg',
  alt: 'A bronze statue of two crossed hands delicately holding a human brain in their fingertips.'  
}, .....

- useState 함수를 쓰게 되면 위와 같이 index가 실시간으로 렌더링 되는 것을 확인할 수 있다.


- useState 동작 방식

- useState를 호출하면 구성 요소가 무엇인지 React에게 알린다.

- 위 코드의 경우 index에 해당된다.

- useState()의 ()안에 값을 통해 초기 값을 전달한다. useState(0)의 경우 index의 초기값은 0이 된다.

const [index, setIndex] = useState(0);

- Button을 클릭하게 되면

setIndex(index + 1)

- 위 함수가 실행되고, React는 위 setter를 통해 index의 값을 변경한다.

728x90