본문 바로가기

WINK-(Web & App)/React.js 스터디

[2024 여름방학 React.js 스터디] 김민서 #3주차

반응형
리액트

 

Virtual DOM을 사용해 작동 성능이 실제로 브라우저에서 DOM을 보여주는 것 보다 속도가 훨씬 빠르다

 

npx create-react-app begin-react
cd begin-react
npm start

 

새로운 리액트 프로젝트 만들기

 

리액트 컴포넌트 만들기

 

// Hello.js
import React from 'react'; // 리액트 불러오기

function Hello() {
    return <div>안녕하세요</div>
}

export default Hello; // 컴포넌트 내보내기 (다른 컴포넌트에서 불러오기 가능)
// App.js
import React from 'react';
import Hello from './Hello';

function App() {
  return (
    <div>
      <Hello />
    </div>
  );
}

export default App;

 

 

JSX

 

리액트에서 생김새를 정의할 때 사용하는 문법

* 리액트에서는 태그를 꼭 닫아주어야 한다

Fragment : 태그를 이름 없이 작성 (브라우저 상에서 별도의 엘리먼트로 나타나지 않는다)

// App.js JSX 안에 자바스크립트 값 사용하기 {} 사용
import React from 'react';
import Hello from './Hello';

function App() {
  const name = 'react';
  return (
    <>
      <Hello />
      <div>{name}</div> 
    </>
  );
}

export default App;

 

// App.js style과 CSS class 설정
import React from 'react';
import Hello from './Hello';
import './App.css';


function App() {
  const name = 'react';
  const style = {
    backgroundColor: 'black', // camelCase 형태로 네이밍
    color: 'aqua',
    fontSize: 24, 
    padding: '1rem' 
  }

  return (
    <>
      <Hello />
      <div style={style}>{name}</div>
      <div className="gray-box"></div> 
    </> 
  );
}

export default App;
// App.css
.gray-box {
  background: gray;
  width: 64px;
  height: 64px;
}

 

JSX 내부의 주석 : {/* 주석 내용 */}

열리는 태그 내부는 // 로도 가능

 

props 로 컴포넌트에게 값 전달하기

 

props는 properties의 줄임말

어떤 값을 컴포넌트에게 전달해줘야 할 때 props를 사용한다

// App.js 에서 name 이라는 값을 전달
import React from 'react';
import Hello from './Hello';

function App() {
  return (
    <Hello name="react" />
  );
}

export default App;
// Hello 컴포넌트에서 name 값을 사용
import React from 'react';

function Hello(props) {
  return <div>안녕하세요 {props.name}</div>
}

export default Hello;
  • 함수의 파라미터에서 비구조화 할당(구조 분해) 문법을 사용하면 코드를 간결하게 작성 가능
  • defaultProps라는 값을 설정하면 props를 지정하지 않아도 기본적으로 사용할 값 설정 가능
  • props.children으로 컴포넌트 태그 사이에 넣은 값을 조회할 수 있음
// Hello.js
import React from 'react';

function Hello({ color, name }) {
    return <div style={{ color }}>안녕하세요 {name}</div>
}

Hello.defaultProps = {
    name: '이름없음'
}

export default Hello;


// App.js
import React from 'react';
import Hello from './Hello';
import Wrapper from './Wrapper';

function App() {
  return (
    <Wrapper>
      <Hello name="react" color="red"/>
      <Hello color="pink"/>
    </Wrapper>
  );
}

export default App;


//Wrapper.js
import React from 'react';

function Wrapper({ children }) {
  const style = {
    border: '2px solid black',
    padding: '16px',
  };
  return (
    <div style={style}>
      {children}
    </div>
  )
}

export default Wrapper;

 

 

조건부 렌더링

 

특정 조건에 따라 다른 결과물을 렌더링

// App.js
import React from 'react';
import Hello from './Hello';
import Wrapper from './Wrapper';


function App() {
  return (
    <Wrapper>
      <Hello name="react" color="red" isSpecial={true}/>
      <Hello color="pink" />
    </Wrapper>
  )
}

export default App;


// Hello.js
import React from 'react';

function Hello({ color, name, isSpecial }) {
  return (
    <div style={{ color }}>
      {isSpecial && <b>*</b>}
      안녕하세요 {name}
    </div>
  );
}

Hello.defaultProps = {
  name: '이름없음'
}

export default Hello;

isSpecial && <b>*</b> : isSpecial이 false일땐 false, isSpecial이 true일땐 <b>*</b>

  • props 값 설정을 생략하면 true로 간주

 

 

useState

 

리액트의 Hooks 중 하나

함수형 컴포넌트에서도 상태를 관리할 수 있다

//Counter.js
import React from 'react';

function Counter() {
  const onIncrease = () => {
    console.log('+1')
  }
  const onDecrease = () => {
    console.log('-1');
  }
  return (
    <div>
      <h1>0</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;

리액트에서 엘리먼트에 이벤트 설정 : on이벤트이름={실행하고싶은함수}

* 함수타입의 값을 넣어주어야한다

// App.js
import React from 'react';
import Counter from './Counter';

function App() {
  return (
    <Counter />
  );
}

export default App;

 

// Counter.js useState 사용
import React, { useState } from 'react'; // useState 불러오기

function Counter() {
  const [number, setNumber] = useState(0); // 배열 비구조화 할당을 통해 각 원소 추출, 첫 번째 원소는 현재 상태 두 번째 원소는 Setter 함수

  const onIncrease = () => {
    setNumber(number + 1);
  }

  const onDecrease = () => {
    setNumber(number - 1);
  } // 파라미터로 전달 받은 값을 최신 상태로 설정

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;

숫자가 바뀐다

// Counter.js 함수형 업데이트
import React, { useState } from 'react';

function Counter() {
  const [number, setNumber] = useState(0);

  const onIncrease = () => {
    setNumber(prevNumber => prevNumber + 1);
  }

  const onDecrease = () => {
    setNumber(prevNumber => prevNumber - 1);
  }

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;

 

 

input 상태 관리하기

 

// InputSample.js
import React, { useState } from 'react';

function InputSample() {
  const [text, setText] = useState('');

  const onChange = (e) => { 
    setText(e.target.value); // 현재 input에 입력한 값이 무엇인지 확인 가능
  };

  const onReset = () => {
    setText('');
  };

  return (
    <div>
      <input onChange={onChange} value={text}  />
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값: {text}</b>
      </div>
    </div>
  );
}

export default InputSample;


// App.js
import React from 'react';
import InputSample from './InputSample';

function App() {
  return (
    <InputSample />
  );
}

export default App;

입력한 값이 하단에 나타나고 초기화 버튼을 누르면 값이 비워진다

 

 

여러 개의 input 상태 관리하기

 

단순히 useState를 여러 번 사용하고 onChange도 여러 개 만들어서 구현할 수 있지만 좋은 방법은 아니다

-> input에 name을 설정하고 이벤트가 발생했을 때 이 값을 참조하기, useState 에서는 문자열이 아니라 객체 형태의 상태를 관리해주기

// InputSample.js
import React, { useState } from 'react';

function InputSample() {
  const [inputs, setInputs] = useState({
    name: '',
    nickname: ''
  });

  const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출

  const onChange = (e) => {
    const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
    setInputs({
      ...inputs, // 기존의 input 객체를 복사한 뒤
      [name]: value // name 키를 가진 값을 value 로 설정
    });
  };

  const onReset = () => {
    setInputs({
      name: '',
      nickname: '',
    })
  };


  return (
    <div>
      <input name="name" placeholder="이름" onChange={onChange} value={name} />
      <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname}/>
      <button onClick={onReset}>초기화</button>
      <div>
        <b>값: </b>
        {name} ({nickname})
      </div>
    </div>
  );
}

export default InputSample;

리액트 상태에서 객체를 수정할 때는 새로운 객체를 만들어서 새로운 객체에 변화를 주고, 이를 상태로 사용해야 한다 (직접 수정 불가)

반응형