생각기록

2023-01-17 useEffect실전, public 폴더 사용, props.children 이란? 본문

강의 정리/React JS

2023-01-17 useEffect실전, public 폴더 사용, props.children 이란?

끼록관 2023. 1. 17. 16:17

전시간 리뷰

더보기

getElementById , querySelector보다 편함

돔 요소에 ref 선언해서 해당 돔 컨트롤

인풋 태그같은 경우는 value값을 받을 수 있다.

돔을 컨트롤 가능하기 때문에 포커스 이동 / dom 컨트롤로 style 적용도 가능

 

useRef 변수처럼 활용하는게 좋다.

스테이트는 값이 변경되면 컴포넌트가 리랜더링 된다.

리랜더링 원치 않고, 값을 저장할 때 쓰는게 useRef입니다.

변수는 리랜더링시 값이 초기화 됨

 

값의 특성을 알고, 상황에 맞게 씁시다

 

React.Fragment

<> </>

 

리액트 특성상 리턴 요소 최상위 부모요소 하나가 존재해야 함

형제요소가 많으면, 리액트가 모르기 때문에 피합니다.

주로 div요소로 썼는데, css 적으로 깨지거나 그런것을 피하기 위해 빈태그를 사용합니다.

 

 

조건부랜더링

컴포넌트를 껏다가 키는..

 

andand 연산자

condition === '감추기' && <Item />

 

삼항 연산자 true, false 

이런식으로 쓴다.

 

 

컴퍼넌트의 Life Cycle

  • 마운트 - 탄생
  • 업데이트 - 리랜더링
  • 언마운트 - 죽음

기존의 세 기능을 하나의 hook , 메소드로 처리 하게 되는게 useEffect

 

 

1. 랜더링마다 실행

인자를 콜백함수 하나만 전달

 

특정 변수, 스테이트값이 변할 때만 실행

2. 의존성 배열

콜백 함수로 작업코드 전달, 배열에 특정값으로 전달하면

의존성 배열 > 해당 배열 값이 변할때만 실행

 

3. 마운트 될때만 실행

배열을 주는 대신 빈배열

 

 

4. 언마운트

useEffect 안에다가 return 콜백함수로

 

 

 

실전 활용?

보통 컴포넌트가 서버로 부터 데이터를 받아와야 하는 상황에서 많이 사용

컴포넌트가 최초 마운트 될 때 유즈이팩트로 서버로 데이터 요청하고

해당 데이터를 state에 등록한다(스테이트값이 바뀌어 리랜더링 하게 됨) > 해당 내용을 랜더링

위와 같은 흐름을 많이 사용한다

 

 

간단한 백엔드 서버 구성하기

백엔드 설치

1. 백엔드 폴더 만들기

2. 안에 gitignore / 노드모듈 제외 시켜주기

 

cors? 

네이버라는 주소가 있는데, 백엔드로 다음으로 하면 위험해서 쓴다?

뭔소린지 이해 못했는데, 밑의 글을 참조해보니 알듯 말듯 하다

https://hannut91.github.io/blogs/infra/cors

 

CORS란 무엇인가? – Yunseok's Dev Blog

 

hannut91.github.io

 

3. cd backend 폴더 들어가서 express와 cors 설치

npm i express cors

 

4. 해당 폴더에 sever.js 파일 만들기

const express = require('express');

// 백앤드 서버와 같은 포트를 쓸수없어서 cors를 피하기위해 모듈 부르기
const cors = require('cors');

const PORT = 4000;
const app = express();

//미들웨어로 cors 어떤 주소에서 요청을 보내도 에러가 뜨지 않는다.
app.use(cors());


app.get('/', (req, res) => {
  const pororoObjArr = [
    {
    name: "뽀로로",
    age: "5",
    nickName: "사고뭉치",
    },
    {
    name: "루피",
    age: "4",
    nickName: "공주님",
    },
    {
    name: "크롱이",
    age: "5",
    nickName: "장난꾸러기",
    },
    ];

    res.status(200).send(JSON.stringify(pororoObjArr));
});

app.listen(PORT, () => {
  console.log(`백엔드 서버가 ${PORT}번에서 작동 중`)
})

Postman 으로 테스트 가능 하지만 안 깔려있어서 

서버에서 보낸 데이터가 출력되어 있습니다.

이제 useEffect로 이것을 해볼것

 

 

 

리액트 컴포넌트 만들기

  • 백엔드 데이터를 받아서 그려줄 컴포넌트 생성
  • 함수가 마운트 되면, axios 함수로 만든 api 데이터를 요청하고, 해당 데이터를  받아서 state에 부여 해보기

axios 깔아주고, import 하기

npm i axiosimport axios from 'axios';

 // UseEffectFetch.jsx
 
import React, { useEffect, useState } from 'react';
import axios from 'axios';

export default function UseEffectFetch() {
  // 배열을 받을거니까 기본값 빈배열로 처리하겠다.
  const [dataArr, setDataArr] = useState([]);

  // 마운트 될때만 데이터를 불러오겠다.
  // 함수를 useEffect 내부에 하는게 아니라! 밖에서 처리합니다.
  async function fetchData() {
    const resFetch = await axios.get('http://localhost:4000');

    // 통신이 제대로 안이루어지면 > if문의 예외처리를 return으로 가독성 있도록
    if (resFetch.status !== 200) return alert('통신 에러');

    // 기억해야할게 초기값이 원시타입이 아니다. 즉, 주소값을 비교한다.
    // 새롭게 변수가 들어가기때매 주소가 달라서 컴포넌트가 변화를 감지해서 리랜더링 됩니다.
    // 가급적 객체, 배열을 덜 사용하는게 좋기는 함
    // aixos는 데이터를 받을때 객체.data로 받는다 /axios가 아닌 그 외는 객체.json();
    const data = await resFetch.data;
    setDataArr(data);
    console.log(data);
    //함수를 선언만
  }
  // 함수 호출
  useEffect(() => {
    fetchData();
  }, []);

axios 문법 오류

axios는 데이터를 .json(); 안해도 바로 들어온다고한다. > resFetch.data;

이렇게 해야 됨!

데이터가 제대로 들어오는 것을 확인 했다.

 

 


받은 데이터를 그려봅시다.

데이터가 일정한 패턴이니 컴포넌트와  props 를 활용해 봅시다.

데이터를 그려주는 컴포넌트를 따로 생성

// ProfileComptnent.jsx

import React from 'react';
// 프롭스 받을거임, 인자에 구조분해 할당
export default function ProfileComptnent({ name, age, nickName }) {
  return (
    <div>
      <h1>이름 : {name} </h1>
      <h1>나이 : {age} </h1>
      <h1>별명 : {nickName} </h1>
    </div>
  );
}

컴포넌트에 map 함수 사용해서 데이터 그려주기

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import ProfileComptnent from './ProfileComptnent';

export default function UseEffectFetch() {
  const [dataArr, setDataArr] = useState([]);
  console.log('useState 실행');

  async function fetchData() {
    const resFetch = await axios.get('http://localhost:4000');
    if (resFetch.status !== 200) return alert('통신 에러');

    const data = await resFetch.data;
    setDataArr(data);
    console.log(data);
  }
  
  useEffect(() => {
    console.log('useEffect 실행');
    fetchData();
  }, []);

  return (
    <div>
      {console.log('리턴 실행')}
      {dataArr.map((el, index) => {
        return (
          <ProfileComptnent
            key={index}
            name={el.name}
            age={el.age}
            nickName={el.nickName}
          />
        );
      })}
    </div>
  );
}

데이터가 바로 들어오지는 않고...

기본 state 값 > return 그림 요소 > useEffect 실행 >  데이터 >  값이 바뀌어 useState 실행 >

return 한 요소를 리랜더링 > 컴포넌트로 데이터 보냄

 

  // useEffect의 실행은 리턴을 한번 그려놓고 그 다음에 호출 됩니다.
  // fetchData가 실행되기전에 return이 실행됨
  // 초기값을 undefined로 주면 js적으로 에러가 발생한다. 그래서 빈 배열!
  // 비원시타입의 초기값을 잘 주는게 중요하다.

 


컴포넌트 꾸미기

인라인으로 꾸미는 방법

jsx 문법을 통해 style속성을 객체로 전달이 가능합니다.

사용에 불편함도 많고, 재사용, 유지보수 면에서 효율적이진 않습니다.

급한 상황이 아니면 사용하지 않습니다.

 

케밥케이스 x 

카멜케이스 o

import React from 'react'

export default function InlineCSS() {
  //케밥 x 카멜 ok
  const divStyle = {
    backgroundColor: 'orange'
  }

  const headingStyle = {
    backgroundColor: 'pink',
    fontWeight: '700',
  }

  const spanStyle = {
    backgroundColor: 'skyblue',
    fontWeight: '700',
  }

  return (
    <div style={divStyle}>
      <h1 style={headingStyle}>CSS 테스트 컴포넌트 입니다.</h1>
      <span style={spanStyle}>해당 컴포넌트를 CSS로 꾸며 보아요</span>
    </div>
  )
}

 

 

기본 css로 꾸미기

  • 컴포넌트의 결과물은 결국 html 코드여서 css로 꾸미기가 가능합니다.
  • 보통 src 폴더에 컴포넌트의 이름과 같은 css파일을 만들어서 사용
  • src > style 폴더 만들고 css 파일 관리 
  • 컴포넌트에 css파일을 import 시켜줘야 한다.

사용법은 import ' 경로 '

import '../style/TestCSS.css'

 

컴포넌트 파일

import React from 'react'
import '../style/TestCSS.css'

export default function TestCSS() {
  return (
    <div className='component-root'>
      <h1>CSS 파일 테스트</h1>
      <span>CSS 적용하기</span>
    </div>
  )
}

css파일

기존 css 쓰듯 케밥 케이스 쓰면 됩니다 

div.component-root {
  background-color: orange;
}

div.component-root h1 {
  color: red;
}

div.component-root span {
  background-color: palevioletred;
  font-weight: 700;
}

 

 


styled components

styled components 는 소규모 컴포넌트 디자인에도 많이 쓴다.

  • 리액트는 기본적으로 컴포넌트 단위가 중심이 되는 구조
  • 컴퍼넌트는 상대적으로 작은 규모로 운영이 되기 때문에 기존의 방식처럼

        css파일을 분리해서 운영할 필요가 크지 않습니다.

  • 따라서 <style>태그를 사용해서 css를 썼던 것 처럼 사용할 수 있도록 하는 요구가 많았습니다.
  • 그래서 탄생한 것이 Styled Components 입니다

 

장점

  • 렌더링되는 요소에 맞춰 자동으로 해당 스타일만 삽입
  • 스타일에 대한 고유 클래스명을 생성합니다. 중복이나 오타 걱정 없습니다.
  • 더 이상 사용되지 않는 CSS를  쉽게 삭제 > 모든 스타일은 특정 요소와 연결되어 있어서 해당 요소가 삭제되면 스타일도 삭제
  • 동적 스타일링이 편해집니다. 이 props가 있다면 A, 없다면 B와 같이 직관적으로 개별 스타일링이 가능

최근에는 스토리북 많이 쓰긴함!

 

설치 및 불러오기

외부라이브러리여서 설치를 해야합니다.

npm i styled-components

설치됨

 

사용방법

const MyDiv = styled.div ` css 문법 `

변수를 선언하듯 styled.태그 ` css 문법 `

.태그 (ex > .div .h1 등등.. )

백팁 내부에 css문법과 동일하게 작성하면 됩니다.

MyDiv

자기만의 이름으로 태그를 구성이 가능

보통 My를 많이 붙임

 

외부 라이브러리니까 import! 해주기

import React from 'react'
import styled from 'styled-components'

//변수를 선언하듯 styled.태그 ` css 문법 `
const MyDiv = styled.div`
  background-color: orange;
`
const MyHeading = styled.h1`
  color: blue;
`
const MySpan = styled.span`
  background-color: pink;
  font-weight: 700;
`

export default function TestStyled() {
  return (
    // 컴포넌트가 아닌 태그임
    <MyDiv>TestStyled
    <MyHeading>h1 태그 입니다.</MyHeading>
    <MySpan>태그 입니다.</MySpan>
    </MyDiv>
  )
}

검사를 하면 임의의 이름으로 되어있다..

 

 

 

 

tip. (``)백틱 문자 내부에 오타없이 작성하는게 부담됩니다.

tip. vscode-styled-components 설치

스니펫도 뜨고 좋다고 생각합니다.

오타 방지율도 줄이고! 

 

 

 

tip. 태그 관리  태그 변경시 아래태그도 같이 변경됨

auto rename tag 설치

 

 


실습1 React 초기 페이지를 Styled 로!

styled. 컴포넌트로 변경해봅시다

그림이 회전하는 것은 

정답

더보기

styled 방식의 keyFrames는

{} 대신 ``백팁

``는 ${변수명}으로 값을 받는다.

{변수값} 을 넣어 변경이 바로 가능합니다.

import logo from '../../src/logo.svg';
import '../../src/App.css';
import styled, { keyframes } from 'styled-components';

const RootDiv = styled.div`
  text-align: center;
`

const AppHeader = styled.header`
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
`
//에니메이션 선언 styled는?
//이미지 로고보다 앞에 위치
const rotation = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
`
const AppLogo = styled.img`
  height: 40vmin;
  pointer-events: none;
  animation: ${rotation} infinite 20s linear;
`

const MyA = styled.a`
   color: #61dafb;
`
function StyledAPP() {
  return (
    <RootDiv>
      <AppHeader>
        <AppLogo src={logo} alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <MyA
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </MyA>
      </AppHeader>
    </RootDiv>
  );
}

export default StyledAPP;

 


Public 폴더로 접근하기

기존 Backend 에서는 public 폴더를 static 이라는 Express 메소드를 용해서 특정 주소 값을 요청하면

바로 public 폴더로 연결 해줬습니다!

public 폴더에 /images 폴더 안에 사진을 넣어봅시다.

이 폴더에 접근하려면..

 

컴포넌트 기준 상대경로로 하면 ../../public/images 위치일 것!

이렇게 접근이 될까?

오류 >>> 소스 폴더 외부로 나가려고 했다 그것은 지원되지 않는다!

소스폴더 외부로 나가려고 했다 그것은 지원되지 않는다!

소스 폴더 외부로 나가려고 했다 그것은 지원되지 않는다!?

백엔드에서 static 폴더를 적용하는것과 같은 의미

외부에서 폴더 구조를 알 수 없도록 하는 것입니다.

절대경로 역시 / 로 하면 c드라이브 부터 시작한다..

static을 설정해야 하는것 같은데..

 

 

페이스북의 도움..!

사실 페이스북은 이미 이마저도 예측하고

npx create-react-app 을 통해 만들면 pubilc 폴더가 자동으로 static 처리가 되게 했다!

어느 위치건 / 를 써서 접근하면 public 폴더가 호출됨

주소값을 /images/사진.jpg 하면 되는 것!

/images/cat.jpg

즉 퍼블릭에 이미지 폴더를 넣어놓고 쓰면 됩니다

물론 src 폴더 파일에서도 사용이 가능!

import React from 'react'
import catImg from '../cat.jpg';

export default function Image() {
  return (
    <>
      <img src="/Images/cat.jpg" alt='고양이'/>
      <img src={catImg} alt='고양이'/>
    </>

  )
}

../(src폴더임) cat.jpg

주소를 통해 폴더 구조가 드러나는 경우를 막기위해 static 처리를 하고 있다.

해당 지정 폴더 밖으로 가는 방식은 막힙니다.

 


Props.children

우리는 props로 값을 보내는 법을 배웠습니다.

상황에따라 html 요소 또는 컴포넌트 자체를 보낼 수 있습니다. 

컴포넌트의 자식 요소를 한꺼번에 전달해 주는 props.children 사용 가능!

 

간단하게 기억하자면!

  • props는 데이터 전달
  • props.children 그림요소 전달

컴포넌트로 감싸여진 자식 요소들 = props.children

 

props는 부모요소에서 보낸다.

FancyBorder.js 컴포넌트는 props의 자식요소를 보더로 감싸는 역할을 해줍니다.

App.js 부모 요소 파일이 해당 컴포넌트에 props로 color를 보내고, 자식요소들을 한번에 보내고 있다.

import React from 'react'

export default function FancyBorder(props) {
  return (
    //기초 props와 children 두개 받아온다.
    //객체라 중괄호! 백팁 : 색을 props에서 받을 거여서 사용
    <div style={{ border: `3px solid ${props.color}`}}>
      {props.children}
    </div>
  )
}

props.children => h1, p 태그 그림요소 전체를 받고 있다.

 

특정 컴포넌트 안에 들어있는 자식요소들을 받아서 쓸수 있다!

말그대로 props의 자식요소들을 말함

 

  • 컴포넌트를 자식으로 삼아 할 수 있다.

 

 

'강의 정리 > React JS' 카테고리의 다른 글

구조 분해 할당  (0) 2023.01.18
2023-01-17 React Router, redux  (0) 2023.01.17
2023-01-12 React useRef  (0) 2023.01.12
2023-01-10  (0) 2023.01.10
2023-01-07 props  (0) 2023.01.07