진행하는 프로젝트의 버튼을 공통컴포넌트로 사용하고 싶어 개발해보았다.

1. 우선 button 의 html 속성을 알아야한다.

 

속성을 확인한 후에 사용할 것만 외부에서 props로 주입해서 사용할 수 있게 만들어준다.

disabled => 해당 버튼이 비활성화됨을 명시

class => css 스타일

onclick => 이벤트 함수

 

그 밖, 

<button> </button>으로 감싸며 입력한 내용을 label로 정의할 예정

 

 

2. React로 Component로 변환

 

props로 받아오는 요소는

label => span 태그로 버튼 내부의 글을 나타냄

styleClass => 적용될 className

disabled => true, false로 활성화 비활성화 조절

onClick => onClick이 일어날 시의 이벤트에 대응

 

import React from 'react';

export default function (props) {
  const { label, styleClass, onClick, disabled} = props;
  return (
    <button className={styleClass} onClick={onClick} disabled={disabled}>
          {label}
    </button>
  );
}

 

3. 다른 컨테이너에서 선언하여 사용

 

import Button from './components/common/Button';
          
<Button 
	label="프론트엔드"
	stylesClass=""
 	onClick={()=> {
		alert('클릭됐다!');
	}}
	disabled={false}
/>

 

결과물

 

스타일링을 안해서 못생겼지만 우선 기능적으로 공통 컴포넌트는 위와 같이 사용하면 된다.

 

Styled Components VS CSS Modules

 

CSS-in-JS(Styled Components) vs CSS-inCSS(CSS Modules) 성능 비교

지난번 포스팅(CSS-in-JS에서 CSS-in-CSS로 바꿔야 하는 이유)에는 CSS-in-JS에서 CSS-in-CSS 방식으로 변경해야 하는 이유에 대해 설명했다. 요약해보면, 다음과 같다. 성능에 초점을 맞춘다면 , 개발 생산

blueshw.github.io

* next.js 로 프로젝트 뼈대 구성 -> next.js 9.3 버전부터 CSS Module을 기본으로 채택하고있다.

 

 

BEM 규칙

 

예제로 이해하는 BEM.

HTML, CSS(flex/grid), UI/UX, Accessibility

naradesign.github.io

 

 

클래스 명명규칙, BEM

개발 공부 초보자의 입장에서 수많은 클래스의 이름을 지정해주는 것은 여간 까다로운 것이 아닙니다. 프로그램이 복잡해질수록 필요한 클래스명도 덩달아 복잡해질텐데 이는 숙련된 개발자들

velog.io

 

 

배포방법

Netlify, Heroku 등

실무 배포 방법 -> develop버전 url / production url 따로 나옴

 

 

Primitive Type & Reference Type

 

 

JavaScript - Primitive Type(원시 타입) vs Reference Type (참조 타입)에 대해 알아보자

JavaScript는 원시 타입과 참조 타입이라는 두가지 자료형을 제공하며 Object를 제외한 모든것들은 Primitive한 성격을 갖고 있다. Primitive Type : 데이터의 실제 값 할당 Reference Type : 데이터의 위치 값만

velog.io

 

스코프와 클로저

 

자바스크립트의 스코프와 클로저 : NHN Cloud Meetup

자바스크립트의 스코프와 클로저

meetup.toast.com

 

프레임없이 순수바닐라자바스크립트로 컴포넌트 단위 개발

 

Vanilla Javascript로 웹 컴포넌트 만들기 | 개발자 황준일

Vanilla Javascript로 웹 컴포넌트 만들기 9월에 넥스트 스텝 (opens new window)에서 진행하는 블랙커피 스터디 (opens new window)에 참여했다. 이 포스트는 스터디 기간동안 계속 고민하며 만들었던 컴포넌트

junilhwang.github.io

 

React의 디자인 패턴

* 리액트는 MVC에서 View를 담당한다.

* View는 멍청해야한다. => 네트워크 통신하고 이런 것 X

* 유닛테스트 할 때마다 네트워크 통신을 해야하는데, 컴포넌트 = View 는 멍청하게 만들어서 네트워크 같은건 class를

따로 만들어 놓고, dependency injection 해주면, 유닛테스트 할 때는 실제로 네트워크 통신을 하는게 아니라, 네트워크 통신 하는 척만 하는 것을 전달해주면 테스트가 빨라진다.

 

👨‍💻 MVC, MVVM, FLUX 패턴과 코드의 흐름 - OOP Study 2

이번주에는 자동차경주게임 미션을 진행했는데, mvc패턴으로 디자인하는 것과 모든 로직에 단위 테스트를 구현하는 것이 중심의 미션이었다. 이번 미션부터는 vanillaJS가 아닌 리액트와 타입스크

taeny.dev

 

우선 React-Native를 쓰려면 기본적으로 React를 알아야한다.

React-Native로 날씨앱 만들기 강의를 수강중인데, import되는 라이브러리중에 처음보는 라이브러리인 PropType이 있어 알아보았다.

목적

 

- 부모로부터 전달받은 컴포넌트의 props 타입 확인을 하기 위해 사용한다.

- 자식 컴포넌트에 명시해놓은 데이터 타입과, 부모로부터 내려받은 타입이 일치하지 않으면 경고문이 뜬다.

 

사용법

 

npm이나 yarn으로 설치부터 한다.

yarn add proptypes

 

prop-types 라이브러리해서 import 하여 사용할 수 있다.

import PropTypes from 'prop-types';

 

- PropTypes는 전달받은 데이터의 유효성을 검증하기 위해 사용된다.

- prop에 유효하지 않는 값이 전달되었을 때 경고문이 Javascript 콘솔에 나타난다.

- propTypes는 개발모드에서만 확인 가능

 

import PropTypes from 'prop-types';

class Greeting extends React.Component {
  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}

Greeting.propTypes = {
  name: PropTypes.string
};

 

PropTypes로 정의가능한 타입

import PropTypes from 'prop-types';

MyComponent.propTypes = {
  // prop가 특정 JS 형식임을 선언할 수 있습니다.
  // 이것들은 기본적으로 모두 선택 사항입니다.
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  
  //News 나 Photos가 아니면 경고 => 배열에 포함된 값 중에 하나 만족
  // 열거형(enum)으로 처리하여 prop가 특정 값들로 제한되도록 할 수 있습니다.
  optionalEnum: PropTypes.oneOf(['News', 'Photos']),

  // 위에 있는 것 모두 `isRequired`와 연결하여 prop가 제공되지 않았을 때
  // 경고가 보이도록 할 수 있습니다. => func이며 필수값으로 안내려올 때 경고!
  requiredFunc: PropTypes.func.isRequired,
  
   // 모든 데이터 타입이 가능한 필수값
  requiredAny: PropTypes.any.isRequired,
  
  // 리액트 엘리먼트
  // <div>123</div> , <Component />
  menu: PropTypes.element,

  // prop가 클래스의 인스턴스임을 선언할 수 있습니다.
  // 이 경우 JavaScript의 instanceof 연산자를 사용합니다.
  optionalMessage: PropTypes.instanceOf(Message),

  // 여러 종류중 하나의 종류가 될 수 있는 객체
  optionalUnion: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
    PropTypes.instanceOf(Message)
  ]),

  // 특정 타입의 행렬
  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 특정 타입의 프로퍼티 값들을 갖는 객체
  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

    
  };

 

 

- defaultProps를 통해 초기 Prop값을 정의할 수도  있음

class Greeting extends React.Component {
  static defaultProps = {
    name: 'stranger'
  }

  render() {
    return (
      <div>Hello, {this.props.name}</div>
    )
  }
}

 

 

함수형

import PropTypes from 'prop-types'

function HelloWorldComponent({ name }) {
  return (
    <div>Hello, {name}</div>
  )
}

HelloWorldComponent.propTypes = {
  name: PropTypes.string
}

export default HelloWorldComponent

 

 

더 많은 내용은 아래 공식 문서 확인

 

PropTypes와 함께 하는 타입 확인 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

Props Deconstructing

 

video_item.jsx 한 줄안에 담긴 것을 꾸며볼 것이다.

 

props를 받아올떄  아래처럼 받아올 수도 있지만.

const VideoItem = props => (

 {props.video.sinppet.thumbnails.mediu.url} //길어짐. 앞의 props를 생략하고 싶다면?

);

 

상위 컴포넌트에서 props를 전달할 때 video로 전달했으면 그 이름을 그대로 써서

const VideoItem = ({video}) => (

 

); 로 써도 되고

 

혹은 다른이름으로 쓰고싶다면.

아래처럼사용해서 videoItem.snippet.thubnail 이런식으로 사용이 가능하다

const VideoItem = ({video: vidoItem}) => (

 

); 

 

만약에 좀 더 deconstructing 하고싶으면 아래처럼. video를 props로 받아오는데 그 안에서 또 snippet을 받아오겠다는 말

const VideoItem = ({video: { snippet } }) => (

//이 경우에 바로 {snippet.title} 로 접근이 가능하다

);

 

 

 

CSS로 컴포넌트 스타일링 해보기

 

1. video_item_module_css 파일을 생성한다.

2. 그리고 위 css를 사용할 컴포넌트에서 import한다.

3. 컴포넌트 jsx 파일에 className={styles.title} 등으로 li / img / p 태그 같은데에 넣어서 스타일링을 넣을 수 있게 구분을 해준다.

{} 로 넣어야함

4. css에 꾸미기 시작한다.

 

* <p>태그에서는 자동으로 margin이 들어간다.

* 드림코딩 앨리 React수업 복습

'[React] Front-End' 카테고리의 다른 글

[FE] axios intercepter  (0) 2021.06.11
[FE] axios 오류처리  (0) 2021.06.11
[FE] React : Redux는 왜 쓸까  (0) 2021.06.09
[FE] React.js : useEffect 의 용도 / 사용 예시  (0) 2021.06.09
[FE] React : REST API  (0) 2021.05.24

https://velopert.com/3533

 

리덕스(Redux)를 왜 쓸까? 그리고 리덕스를 편하게 사용하기 위한 발악 (ii) | VELOPERT.LOG

이 포스트는 이어지는 튜토리얼 입니다. 1편 을 먼저 읽고 오시길 바랍니다. 리덕스의 3가지 규칙 리덕스를 프로젝트에서 사용하게 될 때 알아둬야 할 3가지 규칙이 있습니다. 1. 하나의 애플리케

velopert.com

내용 이해 후 정리 예정

 

forEach: 배열의 모든 원소에 콜백함수를 1회 실행하고 종료

map: 배열의 모든원소에 콜백함수를 1회 실행하고 새로운 배열 리턴해주고 싶을 때 사용

 

map은 return 값이 반드시 있음

 

아래는 habits 라는 배열을 map으로 돌고 하나하나있는 원소의 객체의 id, name, count를 props를 통해 Habit 컴포넌트에 넘기는 과정이다. 

 

habits.jsx

import React, { Component } from 'react';
import Habit from './habit';

class Habits extends Component {
  state = {
    habits: [
      { id: 1, name: 'Reading', count: 0 },
      { id: 2, name: 'Running', count: 0 },
      { id: 3, name: 'Coding', count: 0 },
    ],
  };
  render() {
    return (
      <ul>
        {this.state.habits.map(취미 => (
          <Habit key={취미.id} dadongHobby={취미} /> 
          //dadong으로 부모로(감싸고있는 것으로부터) props 이름을 멋대로 지정해서 옮길 수 있고
          //취미 라는것은 콜백함수에서 임시로 받아오는 데이터의 명! 그것이 바로 habits라는 배열에서 map을 돌며 하나하나 받아오는 요소
        ))}
      </ul>
    );
  }
}

export default Habits;

 

habit.jsx 컴포는트는 render에서 props로 받아온 데이터를 사용할 수 있다.

Habits 컴포넌트에서 habit을 부르면서 데이터를 넣었다. 그때 사용한 요소가 있다 위로 예를 들면 dadong이다.

dadong을 변수에 받아와서 habit.jsx의 render() 함수의 return 값에서 사용할 수 있다. 아래와 같이.

 

class Habit extends Component {

  state = {
    count: 0,
  };

.
.
.



render() {
//    const { name, count } = this.props.habit;
    const { name, count } = this.props.dadongHobby;
    // props 로 가져온 상위 state에서 이름 명이 같아야함 name, count
    // 그리고 map은 콜백으로 호출한것을 모아 새로운 배열 구성

    return (
      <li className="habit">
        <span className="habit-name">{name}</span>
        <span className="habit-count">{count}</span>
        <button
          className="habit-button habit-increase"
          onClick={this.handleIncrement}
        >
          <i className="fas fa-plus-square"></i>
        </button>
        
        
  .
  .
  .
  .
  .
  .

const { name, count }를 통해 props로 받아온 데이터를 넣고(props로 넘겨준 부모컴포넌트의 state로 선언된 객체의 요소명과 같아야 그대로 담긴다.

 

dadong 안에 name과 count 요소가 하나하나 담겨있다. 부모컴포넌트 habits의 habits 배열안에 있는 object들이다.

상위에서 map으로 돌렸기 때문에 habits배열의 요소가 없을때까지 호출된다.

 

 


이벤트 처리하기

 

- 특정컴포넌트에서 prop으로 받은 데이터를 보여주기만 한다면 해당 컴포넌트에서 state는 사용할 필요가 없다.

- habit은 props로 받은 habit을 보여주기만 함. 자체 state가 없음. 내부적으로 데이터 처리 X

- 콜백함수들을 단순히 호출만 해주는걸로 만듬 -> habit컴포넌트!

 

Habits..부모 컴포넌트에 콜백함수 다 가지고 있기. 

-> habits..부모 컴포넌트에서 콜백함수 호출 하면 그냥 다 전달 된느 

 

야 해빗 컴포넌트야! 플러스 버튼이 클릭이되면 onIncrement에 handleIncrement를 전달하고,

 

habits라는 부모 컴포넌트에서 prop으로 Haibt 컴포넌트를 호출해. 그러면 

컴포넌트에 들어있는 habit이라는 오브젝트를 인자로 전달함 ->

그럼 habit 오브젝트에 해당되는 것만 카운트가 올라감

 

Habit에도 prop으로 전달된 콜백함수 호출할 수 있게 만들어놓음

 

 

*출처: 앨리의 드림코딩 React 수업 복습

 

Dream Coding

All Courses, 프론트엔드 중급, 백엔드 타입스크립트 + 객체지향 프로그래밍 마스터 (16) 5.0 average rating

academy.dream-coding.com

 

 

리액트는 state를 직접적을수정하는것은 안된다!(안좋다)

 

 

 

콜백함수 복습

 

'use strict'

console.log('1');

setTimeout(



);   


setTimeout( 함수, 1000초);
function() {
   console.log('2');
}



//1000초 뒤에 해당 함수를 실행하라


setTimeoit(function() {
  console.log('2');
  }, 1000);
  
  

 

 

리액트에서 State가 업데이트 될 때면 반드시 내장함수인 setState를 통해서 업데이트 시켜야한다. 

-> 그냥 state에 있는 변수를 바꿔버리면 안됨. state를 전체적으로 업데이트를 해줘야하는데 그것이 바로 

setState!

 

=> setState를 써야 리액트가 "아~스테이트가 변경되었구나 렌더함수를 다시 호출하자! 라는 식으로 진행이 됨.

class Habit extends Component {

state = {
	count: 0,
};

// 아래는 콜백함수
addCountNumber = () => {
	this.setState({ count: this.state.count+1 })
};

render() {
	return (
    
    )
}

.
.
.
.
.

}

subtractNumber = () => {

    this.setState({ count: this.state.count - 1 });

}

 

아래는 0이하로 안내려가게 하는 코드

subtractNumber = () => {
	const count = this.state.count - 1;
    this.setState({ count: count < 0 ? 0 : count });
};

 

// 구글 크롬개발자도구로 보면

 

props는 즉, 부모 컴포넌트에서 전달받은 properties는 아무것도 없고 

state에는 count 가 1이라는게 들어가있음.

 

 

 

*참고로 setState는 비동기 함수이다.

 

setState 호출 후에 state를 가져오면 변경되지 않은 state가 자꾸 불러져오는 현상이 있음.

setState로 state가 변경되기도 전에 state로 불러와서 문제가 생김.

 

해결을 위해 async/await보다 나이스한 방법은 callback 함수를 이용하는 것.

 

*아래 문서 참고

donghunee.github.io/study/2020/01/26/react/

 

[React]setState callback

플러드 회계앱을 만들던 도중

donghunee.github.io

 

클론한 해당 프로젝트 경로로 들어가서

yarn install
yarn start

 

크롬 개발자 도구로 react관련 앱 다운받으면 component로 해당 사이트에서 구성하는 컴포넌트들을 확인할 수 있다.

 

 

컴포넌트 표시가 안되는 부분은 순수 자바스크립트임

 

- state는 그 컴포넌트에서 가진 데이터

- props는 부모로부터 받아온 데이터가 props

 

 

JSX

 

- 분명 자바스크립트 코드인데 html과 비슷한 코드가 쓰여지는 중

app.jsx

import React from 'react';
import './app.css';

function App() {
  return <h1>Hello :)</h1>
}

export default App;

자바스크립트 코드위에서 간단하게 html처럼 쓸 수 있게 만들어진게 jsx

 

html

class / onclick / 마크업언어

 

jsx

className / onClick / 자바스크립트언어 -> 나중에 바벨이 이것을 모두 html과 자바스크립트로 변화함

{} 를 이용하면 로직사용가능

jsx는 한가지 태그로 감싸줘야함. 두 가지의 자식노드를 이용할때는 묶어야함.

 

묶기위해 원래 div를 씀. 근데 스타일링할때가 아니면 디브 낭비이다!

 

하지만 이제는 React.Fragment 이용하면 가능

아니면 <> 로 이용하면 프래그먼트와 같음!

 

JSX는 다수의 태그를 리턴못함 그래서 묶어서 해야함.

 

import React from 'react';
import './app.css';

function App() {
  const name = 'dadong';
  return (
  <>
  <h1>Hello :) {name}</h1>
  <h1>방가방가</h1>
  </>
  );
}

export default App;

<> 와 </>로 묶어줌

 

아래 방법으로도 가능 -> 여러 자식을 그룹화할 수 있음!

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

 

 

 

사용자 정의 컴포넌트는 반드시 대문자로 시작해야합니다

Element가 소문자로 시작하는 경우에는 <div> 나 <span> 같은 내장 컴포넌트라는 것을 뜻하며 'div' 나 'span' 같은 문자열 형태로 React.createElement에 전달됩니다. <Foo />와 같이 대문자로 시작하는 타입들은 React.createElement(Foo)의 형태로 컴파일 되며 JavaScript 파일 내에 사용자가 정의했거나 import 한 컴포넌트를 가리킵니다.

컴포넌트의 이름은 대문자로 시작하는 것을 추천합니다. 만약 소문자로 시작하는 컴포넌트를 사용해야 한다면, 대문자로 시작하는 변수에 할당한 뒤 JSX에서 이 변수를 사용하세요.

예를 들어 아래의 코드는 예상대로 실행되지 않을 것 입니다.

 

출처

ko.reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized

 

JSX 이해하기 – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

코드블럭을 이용해서 배열에 데이터 넣고 사용가능

 

=> jsx : 자바스크립트 코드와 html 섞어서 사용가능!

 

import React from 'react';
import './app.css';

function App() {
  const name = 'dadong';
  return (
  <>
  <h1>Hello :) {name}</h1>
  {
    ['😺','👻'].map(item => (
      <h2>{item}</h2>
    ))}
  </>
  );
}

export default App;

 

컴포넌트

클래스 / 함수  <- 2가지로 만들 수 있다.

 

 

class: 리액트에서 제공하는 Component라는 클래스를 상속해서 만들 수가 있음

내컴포넌트가 스테이트가 있고, 스테이트가 주기적으로 업데이트 되어야하면 class

-> state라는 오브젝터가 들어있음

-> state가 변경되면 render함수가 호출됨

-> DOM TREE에 올라갔을때, 나왔을때 등 컴포넌트의 상태에 따라 함수를 구현해주면 알아서 해주는 라이프사이클 메소드가 있음

 

function: 간단한 함수로 만들 수 있다.

컴포넌트 데이터가 정적이면 function

-> 함수는 한가지의 기능을 수행하는 단위라서.. state나 라이프사이클메소드가 없음.

-> BUT, react 16.8 부터는 리액트훅이 생김. 그럼 function에서도 state, lifecyclemethod 다 가능

-> 왜 굳이 리액트 훅이 도입되었나?

    기존 클래스컴포넌트에서 할 수 있는 것처럼 동일한 기능이 가능하도록 됨

     그럼 왜 생김? class가 어렵다. 

     클래스에 멤버변수에 접근하면 this.이름 this.나이 <-이게 불편

     functional progrmming이 유행하면서 훅이 도입됨!

    컴포넌트가 마운트되었을때 언마운트되었을때 업데이트 되었을때가 나누어져있었는데, 훅을 이용하면 중복줄일 수 있음

 

 

호불호가 갈려서 class / function(react hook)두 가지 다 이해하는게 중요.

 

Class

 

React.Component

React.PureComponent

 

Function

 

function

memo(function)

React Hook

 

배울 내용들!

 

JSX<-HTML과 차이점?

State 와 Props의 차이점?

SyntheticEvents?

refs? 언제사용?

Lifecycle methods

Lists and keys

developer tools 

techniques

 

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

 

1. 템플릿 React 프로젝트 생성

yarn create react-app template

 

 

2. 해당 프로제트 들어가서 

yarn start


//vsc 실행

code .

 

3.

- public 폴더 하위에 있는 것들은 정적인 아이들을 담는 곳. 사용자가 한번에 받아서 컨텐츠가 변하지 않는 아이들. html img resorce들

- 컨텐츠가 다이나믹하게 동적으로 변화되는 것들이 src (source)에 있음.

(예전 버전은 js가 그대로라면 캐시가 되어있어서 따로 다운받지 않아도됨 ex.webpack관련됨)

 

 

jsx 확장자를 쓰면 리액트 컴포넌트라는 것을 알 수 있음.

파일명은 소문자로! 아이콘도 같이 바뀜

순수 js 인지 리액트 컴포넌트인지 확인하기

 

 

import React from 'react-dom';

-> 리액트는 순수 자바스크립트임. 이걸 이용해서 컴포넌트를 만들어나감.

브라우저는 html css 순수js만 이해가능

그래서

우리가 만든 리액트를 순수 html과 연결해야함

 

사용자에게 궁극적으로 index.html로 배포함

여기있는 root로 연결시켜줌

 

index.js의 react-dom이라는 라이브러리에서 ReactDOM이라는 클래스를 가져옴

-> 그리고 가져온 ReactDOM라는 클래스의 렌더함수를 이용해서 

index.html과 연결한 코드

document.getElementById('root')  ====> 얘를 가지고와서 그 요소에 우리의 root 컴포넌트를 연결시켜준다.

  <React.StrictMode>
    <App />
  </React.StrictMode>

이것이 루트

 

 

index.html에는<body>에

<div id="root"></div>

이렇게 한 줄 있음

 

여기에 index.js에 있는 컴포넌트가 연결되는 것임.

React.StrictMode는 생략가능

 

 

그리고 저기있는 App은 app.jsx에 정의된 컴포넌트임

 

 

3가지 파일을 통해 연결되어있음

html은 화면에 뿌려주는거 브라우저가 이해하는 것!

html과 순수 js를 연동하고, 그 js에서 import해서 jsx에 있는 리액트 컴포넌트를 가져오는 것!

 

index.html 의 22번째줄

 

순수 자바스크립트 index.js의 import. ReactDOM.render()

-> 1,2,4, 6~9줄

-> 8줄의 document.getElementById('root') 

 

app.jsx

-> function 컴포넌트 App()

 

=> root에 결국 app.jsx에 있는 컴포넌트가 그려진다. 

=> react 컴포넌트 결국 html로 변환돼서 브라우저에 나타난다.

 

+ Recent posts