Components and Props

2023. 2. 17. 20:14프레임워크(Framework)/React

<Components와 Props의 정의>

 

Component

1. 리액트는 컴포넌트 기반이라는 중요한 특징이 있다

리액트에서는 모든 페이지가 컴포넌트로 구성되어 있고, 컴포넌트는 또다른 컴포넌트의 조합으로 구성될 수 있다

따라서 이러한 컴포넌트들을 레고 블록 조립하듯 컴포넌트들을 모아서 개발

하나의 컴포넌트를 반복적으로 사용함으로써 전체 코드의 양을 줄일 수 있어서 개발 시간 및 유지보수 비용을 줄일 수 있다

 

리액트 컴포넌트도 js 함수처럼 입력을 받아서 정해진 출력을 내뱉는다

 

 

React component의 역할 : 어떠한 속성들을 입력으로 받아서 그에 맞는 React element를 생성하여 return해주는 것

 

**React element

-React 앱을 구성하는 가장 작은 building 블록들

-객체 형태로 존재

-화면에 보이는 것을 기술한다

 

props 속성

 

 

Props

:Prop이 여러 개인 것을 의미

 

Prop(Property/속성) -- Component의 속성

 

 

props

=> 컴포넌트에 전달한 다양한 정보를 담고 있는 자바스크립트 객체

 

 

 

 


<Props의 특징 및 사용법>

 

Props의 특징

1. Read-Only

-> 값을 변경할 수 없다

 

**다른 Props의 값으로 Element를 생성하려면 어떻게 해야 할까?

-> 새로운 값을 컴포넌트에 전달하여 새로 Element를 생성(이 과정에서 Element가 다시 Rendering되는 것임)

 

**JS 함수의 특징 -- Pure**

function sum(a, b) {
	return a+b;
}

: 입력값(input)을 변경하지 않으며, 같은 입력값에 대해서는 항상 같은 출력값(output)을 리턴

 

**Pure하지 않은 경우**

function withdraw(account, amount) {
	account.total -= amount;
}

이 함수는 입력으로 받은 account의 값을 변경 -> impure하다

 

 

 

Component의 특징 -- React 공식

All React components must act like prue functions with respect to their proprs.

= 모든 리액트 컴포넌트는 그들의 Props에 관해서는 Pure 함수 같은 역할을 해야 한다

=> 모든 리액트 컴포넌트는 Props를 직접 바꿀 수 없고, 같은 Props에 대해서는 항상 같은 결과를 보여줄 것!

 

 

Props의 사용법

**jsx를 사용할 경우**

키, 값 쌍의 형태로 컴포넌트의 props를 넣을 수 있다

function App(props) {
	return (
    	<Profile
            name="소플"
            introduction="안녕하세요, 소플입니다."
            viewCount={1500}
        />
    );
}

위에서는 App 컴포넌트가 나오고, 그 안에서 Profile 컴포넌트를 사용하고 있다

여기서 Profile 컴포넌트에 name, introduction, viewCount라는 세 가지의 속성들을 넣어주었다

여기서 주목해야 할 것은 속성을 넣을 때 {}의 사용 유무

앞서 jsx를 배울 떄, {}를 사용하면 무조건 js 코드가 들어간다 라고 배웠기 때문에 그래서 마찬가지로 props에 값을 넣을 때에도 문자열 이외에 정수, 변수 그리고 다른 컴포넌트들이 들어갈 경우 {}를 사용해서 감싸주기

 

=>props는 이러한 형태의 js 객체가 된다

{
    name: "소플",
    introduction: "안녕하세요, 소플입니다.";
    viewCount: 1500
}

 

 

 

 

**props의 값으로 컴포넌트 넣기**

function App(props) {
	return {
    	<Layout
            width={2560}
            height={1440}
            header={
            	<Header title="소플의 블로그입니다." />
            }
            footer={
            	<Footer />
            }
        />
    );
}

=> Layout 컴포넌트의 props로는 정수값을 가진 width, height과 React element로 header, footer가 들어오게 됨

 

=>이처럼 jsx를 사용하는 경우에는 간단하게 컴포넌트를 넣을 수 있음

 

 

 

**jsx를 사용하지 않는 경우**

 

※createElement

React.createElement(
    type,
    [props],
    [...children]
)

props에 js 객체를 넣으면 해당 컴포넌트의 props가 됨

 

React.createElement(
    Profile,
    {
        name: "소플",
        introduction: "안녕하세요, 소플입니다.",
        viewCount: 1500
    },
    null
);

 

 

 

=> props를 jsx를 사용해서 하는 것을 추천

 

 

 


 

 

 

 

<Component 만들기 및 렌더링>

 

Component 만들기

 

 

요즘에는 함수 컴포넌트의 훅(hook)을 많이 사용

 

Function Component

function Welcome(props) {
    return <h1>안녕, {props.name}</h1>
}

 

 

 

Class Component

class Welcome extends React.Component {
    render() {
        return <h1>안녕, {this.props.name}</h1>
    }
}

function component와의 차이점

: 리액트의 모든 클래스 컴포넌트는 React.Component를 상속 받아서 만든다는 것

 

 

 

Component의 이름

: Component 이름은 항상 대문자로 시작해야 한다!

이유) 리액트는 소문자로 시작하는 컴포넌트를 돔 태그로 이해하기 때문이다

ex) div나 span과 같은 것들은 내장 컴포넌트라는 것을 뜻하며 div나 span과 같은 문자열 형태로 React.createElement에 전달됨. 하지만 대문자로 시작하는 경우 뿌???같은 경우 React.createElement 뿌??? 형태로 컴파일되며, 자바스크립트 파일 내에서 사용자가 정의했거나 import한 컴포넌트를 가리킨다.

 

 

HTML div 태그로 인식

const element = <div />;

->DOM 태그를 사용하여 element를 만든 것

 

 

Welcome이라는 리액트 Component로 인식

const element = <Welcome name="인제" />;

만약 이것이 소문자(welcome)로 시작했다면 리액트는 이것을 컴포넌트가 아니라 돔 태그라고 인식하게 됨

-> 에러 발생 가능성

 

만약 컴포넌트의 이름을 꼭 소문자로 시작하고 싶다면 먼저 대문자로 시작하는 변수에 할당한 뒤 이 변수를 사용하면 됨

하지만 거진 대문자 사용하자\

 

 

Component 렌더링

앞에서 말한 바와 같이 컴포넌트는 붕어빵 틀 역할을 하기 떄문에 실제로 컴포넌트가 화면에 렌더링되는 것은 아님

 

따라서 렌더링을 하기 위해서는 컴포넌트로부터 element를 만들어야 됨

 

DOM 태그를 사용한 element

const element = <div />;

 

 

사용자가 정의한 Component를 사용한 element

const element = <Welcome name="인제" />;

 

 

 

function Welcome(props) {
    return <h1>안녕, {props.name}</h1>
}

const element = <Welcome name="인제" />;
ReactDOM.render(
    element,
    document.getElementById('root')
);

 

 

 

Component 합성

리액트에서는 컴포넌트 안에 또다른 컴포넌트를 사용할 수 있다.

복잡한 화면을 여러 개의 컴포넌트로 나눠서 구현 가능!

 

function Welcome(props) {
    return <h1>Hello, {props.name}</h1>;
}

function App(props) {
    return (
        <div>
            <Welcome name="Mike" />
            <Welcome name="Steve" />
            <Welcome name="Jane" />
        </div>
    )
}

ReactDOM.render(
    <APP />,
    document.getElementById('root')
);

 

 

 

Component 추출

큰 컴포넌트를 산산조각 내자!

재사용성 및 개발속도가 올라감

 

function Comment(props) {
    return (
        <div className="comment">
            <div className="user-info">
                <img className="avatar"
                    src={props.author.avatarUrl}
                    alt={props.author.name}
                />
                <div className="user-info-name">
                    {props.author.name}
                </div>
            </div>
            
            <div className="comment-text">
                {props.text}
            </div>
            
            <div className="comment-date">
                {formatDate(props.date)}
            </div>
        </div>
    );
}
props = {
    author: {
        name: "소플",
        avatarUrl: "https://...",
    },
    text: "댓글입니다.",
    data: Date.now(),
}

 

 


<실습>

 

[src>>chapter_05>>Comment.jsx]

import React from "react";

const styles = {
    wrapper: {
        margin: 8,
        padding: 8,
        display: "flex",
        flexDirection: "row",
        border: "1px solid grey",
        borderRadius: 16,
    },
    imageContainer: {},
    image: {
        width: 50,
        height: 50,
        borderRadius: 25,
    },
    contentContainer: {
        marginLeft: 8,
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
    },
    nameText: {
        color: "black",
        fontSize: 16,
        fontWeight: "bold",
    },
    commentText: {
        color: "black",
        fontSize: 16,
    },
};

function Comment(props) {
    return (
        <div style={styles.wrapper}>
            <div style={styles.imageContainer}>
                <img
                    src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png"
                    style={styles.image}
                />
            </div>

            <div style={styles.contentContainer}>
                <span style={styles.nameText}>{props.name}</span>
                <span style={styles.commentText}>{props.comment}</span>
            </div>
        </div>
    );
}
export default Comment;

 

[src>>chapter_05>>CommentList.jsx]

import React from "react";
import Comment from "./Comment";

const comments = [
    {
        name:"이인제",
        comment:"안녕하세요, 소플입니다.",
    },
    {
        name:"유재석",
        comment:"리액트 재미있어요~!",
    },
    {
        name:"강민경",
        comment:"저도 리액트 배워보고 싶어요!!",
    },
];

function CommentList(props) {
    return (
        <div>
            {comments.map((comment)=>{
                return (
                    <Comment name={comment.name} comment={comment.comment} />
                );
            })};
        </div>
    );
}
export default CommentList;

 

[src>>index.js]

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

import Library from './chapter_03/Library';
import Clock from './chapter_04/Clock';
import CommentList from './chapter_05/CommentList';

ReactDOM.render(
  <React.StrictMode>
    <CommentList/>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

'프레임워크(Framework) > React' 카테고리의 다른 글

Hooks  (0) 2023.02.18
State and Lifecycle  (0) 2023.02.18
Rendering Elements  (0) 2023.02.15
React 실행 시 오류 해결 방법  (0) 2023.02.15
JSX의 정의와 역할  (0) 2023.02.06