[Udemy] React - CRA, JSX, State, Props

productuidev·2022년 4월 16일
0

React Study

목록 보기
18/49
post-thumbnail

React 입문

Udemy - 한입크기로 잘라 먹는 리액트

React 리액트 프레임워크 라이브러리



Creat React App

CRA JSX State Props

📌 React App을 만드는 방법

✔️ 이미 세팅 완료된 패키지

리액트를 더 잘 활용하기 위해 추가적인 라이브러리들이 필요한데 Webpack과 Babel이 필요하다.

  • React.js : Node 기반의 자바스크립트 UI 라이브러리
  • Webpack : 다수의 자바스크립트 파일을 하나의 파일로 합쳐주는 모듈 번들 라이브러리
  • Babel : JSX 등의 쉽고 직관적인 자바스크립트 문법을 사용할 수 있도록 해주는 라이브러리

그런데 언제 다 설정하지?

☑️ Boiler Plate : 어떤 기술에 대해 미리 기초 설정 작업이 되 있는 것.
보일러를 찍어내는 틀. 마치 보일러를 찍어내듯, 서비스를 개발할 수 있는 빵 틀의 역할을 하는 패키지 의미 (공장에서 빵틀에 빵을 찍어내듯이)

☑️ npx : npm을 편리하게 이용하기 위한 도구. 설치되어 있지 않는 패키지를 딱 1번만 쓰고 싶을 때 사용하는 명령어

☑️ Node JS 기반으로 웹 서버 위에서 동작하고 있다 (localhost:3000 자기자신에게 가는 주소)

☑️ node_modules : 많은 모듈 패키지 설치, node_modules가 없거나 지워져도 package.json이나 package-lock.json 또는 npm i로 다시 설치할 수 있음.

☑️ public / src 디렉토리

☑️ App.js (HTML과 JS를 합친 것 같은 느낌)

☑️ index.js

☑️ JSX : JavaScript Extension. HTML 문법을 JavaScript 코드 내부에 쓴 것. JavaScript의 확장 버전.

☑️ 컴포넌트 방식 : JSX 문법을 사용해서 웹에 필요한 요소를 함수에 담아서 리턴 후 내보내서 index.js같은 다른 파일에서도 사용할 수 있게 함

☑️ ESModule System : Common JS Module System이 아닌 리액트가 주로 사용하는 방식 (ex: export default App같이 App이라는 함수를 내보내면 다른 파일에서 import App from 경로처럼 사용 가능하다는 뜻임) * export default는 1개만 내보낼 수 있음.

☑️ 우리가 다른 패키지를 불러와서 사용하거나 보일러 플레이트가 아닌 직접 구축하고자 할 때는 ESModule System이 아닌 Common JS Module System을 사용하는 경우도 있음


📌 JSX

☑️ HTML with JavaScript
☑️ Closing tag, Self Closing tag
☑️ JSX expressions must have one parent elements to return.

App.js

1) <div className="App"></div>

2) import React from "react";
<React.Fragments>
</React.Fragments>

3) import React from "react";
<>
</>

☑️ 컴포넌트 쓰는 파일에서는 만약 react 기능을 쓰지 않는다면 굳이 import React하지 않아도 상관없음 (사용하는 파일이면 import)
☑️ CSS Styling
1) import './App.css'; (App.css에서 작업)
2) inline으로 객체를 만들어서 스타일링 가능

function App() {

  const style = {
    App: { backgroundColor:"#282c34", },
    h2: { color:"#fff", },
    boldTxt: { color:"#61dafb", },
  };

  return (
    <div className="App" style={style.App}>
      <header className="App-header">
        <h2 style={style.h2}>리액트</h2>
        <strong class="boldTxt" style={style.boldTxt}>React.js</strong>
      </header>
    </div>
  );
}

☑️ 자바스크립트의 값을 사용하는 방법 : 변수, 표현식, 함수 호출

// 📝 조건부 렌더링

function App() {

  const number = 5;

  return (
    <div className="App">
      <header className="App-header">
        <p>{number}는 : {number % 2 === 0 ? "짝수" : "홀수"}</p>
      </header>
    </div>
  );
}

📌 State

☑️ 인간의 허기에 빗대어 생각하기 (배고픔 - 식사 - 적당함 - 시간 흐름 - 배고픔)
☑️ 계속해서 변화하는 특정 상태. 상태에 따라 각각 다른 동작을 함.
☑️ 컴포넌트가 가지는 동적인 데이터

✔️ Dark/Light Theme UI

Dark/Light Mode도 상태라고 생각할 수 있는데, 어떤 컴포넌트가 상태라는 테마를 가지고, 그 테마라는 상태는 Dark와 Light라는 값을 가질 수 있음. 사용자는 보이는 것처럼 Switch(Toggle UI)를 통해 상태를 Dark/Light 둘 중 하나로 변경시킬 수 있음. 리액트에서 말하는 state는 컴포넌트가 갖는 테마처럼 계속 값이 바뀌는 동적인 데이터이고 이 상태를 바꾸는 관리는 이걸 가진 컴포넌트가 직접 관리하게 된다.

☑️ 예제 : button counter

import React, {useState} from "react"; 

const Counter = () => {
  
  // 0에서 출발
  // 1씩 증가하고 1씩 감소하는 count 상태

  // console.log("counter 호출!");

  const [count, setCount] = useState(0);
  
  // useState는 React의 메서드이고, 이것으로 배열을 반환하고 배열의 비구조화할당을 통해서
  // 0번째 index는 count, 1번째 index는 setCount 라는 상수로 받아 옴
  // 0번째 index인 count 인자는 상태의 값으로 사용됨
  // 1번째 index인 setCount 인자는 count를 변화시키는 상태변화 함수로써 사용됨
  // useState(0)은 count라는 상태를 만드는데에 초기값으로 사용됨 ---> 0에서 출발
  
  // 상태 전달
  const onIncrease = () => {
    setCount(count + 1); // 1씩 증가 
  }

  const onDecrease = () => {
    setCount(count - 1); // 1씩 감소
  }

  const [count2, setCount2] = useState(0);

  const onIncrease2 = () => {
    setCount2(count2 + 1); // 1씩 증가 
  }

  const onDecrease2 = () => {
    setCount2(count2 - 1); // 1씩 감소
  }

  return (
    <div>
      <h2>{count}</h2> {/* 이런 식으로 count를 jsx에서 반환해서 화면에 표시 */}
      <button onClick={onIncrease}>+</button> {/* 버튼을 눌렀을 때 이 함수가 수행되어야 하니까 onClick에 onIncrease 함수를 넣어준다 */}
      <button onClick={onDecrease}>-</button>

      <h2>{count2}</h2> {/* 이런 식으로 count를 jsx에서 반환해서 화면에 표시 */}
      <button onClick={onIncrease2}>+</button> {/* 버튼을 눌렀을 때 이 함수가 수행되어야 하니까 onClick에 onIncrease 함수를 넣어준다 */}
      <button onClick={onDecrease2}>-</button>
    </div>
  )
}

export default Counter;

✔️ 동적인 데이터 State

useState로 상태를 만들면 count라는 이름으로 상태값을 불러올 수 있고, setCount라는 상태로 업데이트(변화)시킬 수 있다. (초기값은 useState() 안에 넣어준다)
결론적으로 지금 화면에 표시되는 게 실시간으로 바뀐다는 건 count state가 바뀔 때마다(업데이트될 때마다) Counter라는 함수가 return(반환)을 다시한다고 생각할 수 있다. 왜냐하면 결국에 App 컴포넌트가 Counter 컴포넌트를 호출하고 반환받은 HTML을 화면에 표시하는 것이기 때문에 Counter 컴포넌트가 리턴을 다시하는 것이다. (= 화면을 새로 그린다 = re-render)
여기서 알 수 있는 건 자신이 가지고 있는 state 상태가 변화하면 화면을 다시 그려 re-render를 한다. 그러니까 이 함수가 다시 호출된다라고 생각하면 된다.
리액트에서는 어떤 컴포넌트의 상태가 바뀌면 그 컴포넌트가 다시 렌더링 된다. 또한 counter 컴포넌트가 state를 2개 가져도 상관은 없지만, 상태변화 함수는 상수 선언하는 것이므로 이름이 겹치면 안된다. 리액트는 여러 개의 state를 하나의 컴포넌트가 가져도 문제가 되지 않고, state는 매우 짧은 코드와 문법으로 화면에 나타나는 데이터를 쉽게 교체하고 업데이트할 수 있도록 도와준다. 이 리액트의 state를 잘 이용하면 사용자의 동작들에 반응해서 엘리먼트가 동적으로 바뀌는 사이트를 만들 수 있다.


📌 Props

☑️ 컴포넌트에 데이터를 전달하는 방법 : 컴포넌트에게 데이터를 전달하는 가장 기본적인, 효율적인 방법
☑️ 이전 Counter 컴포넌트 예제에 이어서 만약에 App 컴포넌트에서 Counter 컴포넌트에게 이 Counter의 초기값을 0이 아닌 App 컴포넌트가 전달하는 값으로 쓰라는 명령을 내리고 싶다면?
☑️ Prop : 부모 컴포넌트인 App 컴포넌트에서 자식 컴포넌트인 Counter 컴포넌트에게 어떤 값에 이름을 붙여서 전달하는 방식 (복수형이면 Props)
☑️ 이전에 객체를 배울 때 얘기했던 Properties를 줄인 의미

// Counter 컴포넌트에서 이렇게 부모에서 내려준 Props를 매개 변수를 통해서 받아서 사용할 수 있다
function App() {
	const number = 5;
    
    return (
    	<div>
        	<Counter initialValue={5} /> {/* 여기서 */}
        </div>
    )
}

// 매개변수로 props를 전달해서 내려줌 
const Counter = (props) => {
	console.log(props); // 객체안에 담겨서 온다
    
    const [count, setCount] = useState(props.initialValue);
    // 이렇게 객체로 전달 온 props를 Counter 컴포넌트에서 꺼내 쓰려면 점표기법으로 접근해서 사용 가능
}

☑️ 자식 컴포넌트에게 전달해야 하는 Props들을 객체로 만들어서 전달 가능
☑️ 이 때 객체를 펼쳐서 전달하는 spread 연산자를 통해서 전달해도 똑같이 카운터 컴포넌트에서 받아서 출력할 수 있음
☑️ 받는 쪽에서도 똑같이 객체로 받는다 했으니까 비구조화 할당을 통해서 받을수도 있음
☑️ 비구조화 할당을 통해서 매개 변수로 전달되는 props라는 객체에서 initialValue 값만 딱 꺼내쓴 것임.

// 객체, spread 연산자
function App() {

  const counterProps = { a:1,b:2,c:3,d:4,e:5,initialValue=5 }

  return (
    <Container>
      <div>
        <Counter {...counterProps} />
      </div>
    </Container>
  );
}


// 비구조화 할당
const Counter = ({initialValue}) => {
	const [count, setCount] = useState(props.initialValue);
}

☑️ 만약 이 Counter 컴포넌트에게 App 컴포넌트에서 initialValue를 내려주려다가 깜빡했다면?
---> 아무것도 전달하지 않았기 때문에 undefined
---> +버튼을 누르면 setCount(count + 1)니까 NaN이 됨 (Not-a-Number)
----> 이런 식으로 의도치 않게 특정 Props가 이렇게 undefined로 전달될 것 같을 때는?
☑️ 부모 컴포넌트인 App 컴포넌트에서 Props를 내려준 적이 없어도 이 Counter 컴포넌트에서 받은 value는 defaultProps에 의해서 0으로 고정됨
☑️ defautProps : 전달받지 못한 Props의 기본값을 설정해서 에러 방지할 수 있음

// defaultProps 설정해주기
Counter.defaultProps = { initialValue:0 }

☑️ 동적 데이터 전달하기 : state 전달하기
☑️ Counter 컴포넌트 안에 있는 state가 현재 홀수인지 짝수인지 실시간으로 알려주는 기능
☑️ count를 2로 나눴을 때 나머지가 0이면 짝수, 아니면 홀수 이런 상태로 state와 props을 이용해서 동적인 데이터를 계속해서 바꿔가면서 전달할 수 있음

// 현재 이 Counter 컴포넌트의 count를 받으려면 Props로 받는 방법밖에 없음

// OddEvenResults.js
const OddEventResult = ({count}) => {
  console.log(count);
  return <>{count % 2 === 0 ? "짝수" : "홀수"}</>;
};

// Counter.js
<OddEventResult count={count} />

☑️ OddEvenResult 컴포넌트가 이 Counter의 state가 바뀔 때마다 계속 다른 거를 render하는 걸 볼 수 있는데 이렇게 리액트의 컴포넌트는 부모가 내려주는 Props가 변경되면 브라우저에서 re-render 하게 됨 ---> 부모 요소의 state가 바뀌게 되면 자식 요소의 컴포넌트도 계속 re-render된다

✔️ Props로 동적인 데이터 State 전달 개념

  • 리액트의 컴포넌트는 본인이 관리하고 본인이 가진 state가 바뀔 때마다 re-render가 된다
  • 나에게 내려오는 Props가 바뀔 때마다 re-render된다
  • 둘 다 아니어도 내 부모가 re-render가 되면 나도 re-render가 된다

☑️ Props는 뭐든지 전달할 수 있어서 컴포넌트 자체도 전달 가능
☑️ console.log로 확인 시 typeof: Symbol(react.element)로 받은 것 확인 가능

src/Container.js

// Container 컴포넌트는 children이라는 Props를 받을 것임

const Container = ({children}) => {

  console.log(children);

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



src/App.js


// App 컴포넌트에서 Container 컴포넌트의 자식으로 배치된 요소들은
// Container 컴포넌트에 children이란 Props로 전달되었음
// 그래서 children의 JSX 요소들이 전달이 되었고
// 결론적으로 이런 식으로 값처럼 활용해서 div를 바깥에 두고 감사서 render된 것 확인 가능

function App() {

  const counterProps = { a:1,b:2,c:3,d:4,e:5, }

  return (
    <Container>
      <div>
        <Counter {...counterProps} />
      </div>
    </Container>
  );
}

주말이라 열공모드로 강의 집중에서 들으려고 했는데..
state 상태 부분에서 배고픔 이야기하니까 덩달아 배고파졌다. (단순한 닌겡..)
밥먹고 갔다와서 해야지...했다가 몰입 실패 (결국 props는 새벽에 다시 들었다는 이야기)

profile
Today I Learned Log (Web Publisher/UI Developer)

0개의 댓글