공부한것/React

[React] 몰아듣기...

flyda 2022. 7. 16. 02:25

리액트를 쓰는 이유 : https://github.com/academind/react-complete-guide-code/tree/01-getting-started/code/react-vs-vanilla-js-example

리액트의 대안 : https://academind.com/tutorials/angular-vs-react-vs-vue-my-thoughts

-----------------

nodejs 설치  : https://nodejs.org/ko/

강의에서는 최신 버전을 설치하라고 했지만 나는 LTS파이다... ㅋㅋㅋ

이제 리액트 프로잭트 만들 수 있다!! 

https://github.com/facebook/create-react-app

 

GitHub - facebook/create-react-app: Set up a modern web app by running one command.

Set up a modern web app by running one command. Contribute to facebook/create-react-app development by creating an account on GitHub.

github.com

 

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

 

 vscode를 추천함! 

prettier - code formatter 추천함 Keyboard Shortcuts에서 ‘format document’를 검색하면 단축키 사용 가능

 

리액트 이제 시작!!!

index.js 파일!!

import React from 'react';
import ReactDOM from 'react-dom';

import './index.css';
import App from './App';
//처음에 브라우저에서 이 프로잭트를 접근했을 때 진입점 파일!!! 


ReactDOM.render(<App />, document.getElementById('root')); //이 코드의 실행결과를 브라우저에 보여줌!!

<App /> 은 js 속의 html 코드이고  사실   jsx 문법임!!  그리고 두번째 인수는 <App />가 어디에 렌더링 되어야 하는지 보여준다. 여기에서index.html 파일에서  root라는 아이디를 가진 요소를 찾아서 src 폴더 안에 있는  app.js 파일을 넣으라는(?) 이야기이다!! 

<App />는 개발자가 만든 컴포넌트이다!! 컴포넌트는 무조건 브라우저에 렌러일 될 수 있는 값을 반환해야하는데, 보통 html 코드이다.
//src/app.js
function App() {
  return <div>Hello!</div>; //컴포넌트는 무조건 브라우저에 렌러일 될 수 있는 값을 반환해야하는데, 보통 html 코드이다.
}

export default App;

 

컴포넌트에서 return하는 값은 html처럼 보이지만 사실은 js이기 때문에 class가 아니고 className으로 작성해야한다!!

function App(){
  return(
    <div>
      <h1>My Todos</h1>
      <div className='card'> 
        <h2>TITLE</h2>
        <div className="actions">
          <button className="btn">Delete</button>
        </div>
      </div>
    </div>
  );
}
export default App;

하지만 className은 좀 특이한 경우라고 한다! 

 

다른 컴포넌트 빌드 및 재사용하는 방법 

함수의 이름은 대문자로 시작해야한다!!  내장 html element와 구별해주기 위해서이다!! (뷰랑비슷한데?!) 개발자가 만든 요소라면 무조건 대문자1!! 대문자!!! 

// src/component/Todo.js
function Todo() {
  return (
    <div className='card'> 
      <h2>TITLE</h2>
      <div className="actions">
        <button className="btn">Delete</button>
      </div>
    </div>
  );
}

export default Todo;

위에서 만든 컴포넌트를 이렇게 html 요소 처럼 사용하면 된다. 

import Todo from './component/Todo'

function App(){
  return(
    <div>
      <h1>My Todos</h1>
      <Todo />
      <Todo />
      <Todo />
      <Todo />
    </div>
  );
}
export default App;

하지만 이렇게 사용하면 문제가 있는데!!!! 바로.... Todo 컴포넌트가 항상 같은 값만 출력한다는 것이다!! 

그래서 Todo 컴포넌트를 사용하는 app.js에서 데이터를 넘겨주자1!! 

 

"props" 및 동적 콘텐츠 작업하기 

 

//App.js

import Todo from './component/Todo'

function App(){
  return(
    <div>
      <h1>My Todos</h1>
      <Todo text='리액트 배우기' />
      <Todo text='뷰 배우기' />
      <Todo text='바닐라 배우기' />
    
    </div>
  );
}
export default App;

Todo에 text라는 속성을 만들어주고!! 각자 원하는 값을 넣어준다. 

이후에 Todo 컴포넌트에서는 props라는 매개변수를 넣어주고 props.text로 접근해서 사용해준다!!  부모한테 속성 값을 받아서 쓰는거다!! 

// Todo.js

function Todo(props) {
  return (
    <div className='card'> 
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn">Delete</button>
      </div>
    </div>
  );
}

export default Todo;

{ } 중괄호(동적표현식)를 넣어주면 js코드로 동작한다!! 여기에는 {2 + 2}와 같이 한 줄의 표현식을 작성할 수 있다. 하지만 if문과 같은 block문은 작성할 수 없다. 

 

이벤트 처리하기!! 

onClick에 동적표현식을 쓰는데, 그 안에는 함수를 호출(실행)하면 안된다!! 그냥 함수값을 넣어야한다. (걍 호출하는 소괄호'()'를 빼고 함수 이름만 넣으라는 뜻) 함수를 실행하면 js와 리액트가 코드를 검증할 때 실행이 되어 버리기 떄문이다!! 

function Todo(props) {

  function deleteHandler() {
    console.log('clicked!!');
    console.log(props.text);
  }

  return (
    <div className='card'> 
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn" onClick={deleteHandler} >Delete</button>
      </div>
    </div>
  );
}

export default Todo;

 

 

더 많은 컴포넌트 추가하기!! 

컴포넌트에서 길고 너무 복잡한 로직을 관리하면 안된다! 다 작은 단위로 쪼개주는 것이 좋다. 

modal이랑 backdrop 컴포넌트를 만들고 사용해보겠다!! 

//modal.js

function Modal() {
  return 
  <div className="modal">
    <p>Are you Sure??</p>
    <button className="btn btn--alt"> Cancel</button>
    <button className="btn">Confirm</button>
  </div>
}
export default Modal;
//Backdrop js

function Backdrop() {
  return <div className="backdrop" />
}

export default Backdrop;

이렇게 두 개의 컴포넌트를 만들어 준 다음에 App.js에서 불러온 다음 사용할 수 있다. 

//App.js

import Todo from './component/Todo'
import Modal from './component/Modal';
import Backdrop from './component/Backdrop';

function App(){
  return(
    <div>
      <h1>My Todos</h1>
      <Todo text='리액트 배우기' />
      <Todo text='뷰 배우기' />
      <Todo text='바닐라 배우기' />
      <Modal />
      <Backdrop />
    </div>
  );
}
export default App;

 하지만 이렇게 하면 모달창에 아무런 반응이 없다. 즉 완전히 정적인 사이트이다!! 이를 해결하기 위해서 state를 알아보자!!! 

 

State란..?  

지금 상태에서 다른 상태로 바뀔 수 있어야 한다1! 예를들면 버튼을 누르면 modal과 backdrop이 열리고 버튼이나 backdrop을 누르면 모달이 닫혀야 한다!!  https://github.com/dadafly1244/TIL/tree/e99005de84d929fe23786c19d2dffaea4107a8b6

import {useState} from 'react' 를 통해서 우리는 원하는 상태를 등록할 수 있다 

useState의 초기 값을 매개 변수로 전달할 수있음. 배열을 리턴함. 첫번째 값은 현재 state의 snapshot, 

 {modalIsOpen && <Modal />} 만약 false 면 모달을 열지 않고 true면 모달을 열어라는 뜻!!!  
import Todo from './component/Todo'


function App(){
  return(
    <div>
      <h1>My Todos</h1>
      <Todo text='리액트 배우기' />
      <Todo text='뷰 배우기' />
      <Todo text='바닐라 배우기' />
    </div>
  );
}
export default App;
import { useState } from 'react'

import Modal from './Modal';
import Backdrop from './Backdrop';

function Todo(props) {
  const [modalIsOpen, setModalIsOpen ]= useState(false);
  function deleteHandler() {
    console.log('clicked!!');
    console.log(props.text);
  }

  return (
    <div className='card'> 
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn" onClick={deleteHandler} >Delete</button>
      </div>
      {modalIsOpen && <Modal />} 
      {modalIsOpen && <Backdrop />}
    </div>
  );
}

export default Todo;

 

event props로 작업하기. 기능을 props로 전달하기 

함수는 일급객체이기 때문에 값으로 전달할 수 있다. 그리고 backdrop과 같이 우리가 만든 컴포넌트는 직접 onClick과 같은 이벤트를 props로 전달해주어야 한다!!  

{modalIsOpen && <Backdrop onClick={closeModalHandler} />} 에서 우리가 만든 것이기 때문에 onClick말고 다른 이름을 사용해도 된다!!
import { useState } from 'react'

import Modal from './Modal';
import Backdrop from './Backdrop';

function Todo(props) {
  const [modalIsOpen, setModalIsOpen ]= useState(false);
  function deleteHandler() {
    // console.log('clicked!!');
    // console.log(props.text);
    setModalIsOpen(true);
  }
  function closeModalHandler () {
    setModalIsOpen(false)
  }

  return (
    <div className='card'> 
      <h2>{props.text}</h2>
      <div className="actions">
        <button className="btn" onClick={deleteHandler} >Delete</button>
      </div>
      {modalIsOpen && <Modal />} 
      {modalIsOpen && <Backdrop onClick={closeModalHandler} />}
    </div>
  );
}

export default Todo;
function Backdrop(props) {
  return <div className="backdrop" onClick={props.onClick} />
}

export default Backdrop;

그럼 사용할때도 'props.설정한이름'으로 불러오면 된다!!