2022-01-07 T.I.L

정종훈·2022년 3월 1일
0

T.I.L

목록 보기
6/20

React State & Props intro

  • state, props의 개념에 대해서 이해하고, 실제 프로젝트에 바르게 적용할 수 있다.=>
    state: 상태, 변할수 있는 값 . 컴포넌트 외부에서 변화하는 값
    props: 컴포넌트의 속성, 부모 컴포넌트(상위컴포넌트)로 부터 전달받는값

  • React 함수 컴포넌트(React Function Component)에서 state hook을 이용하여 state를 정의 및 변경할 수 있다.=>
    ㅇㅋ 할수 있음
  • React 컴포넌트(React Component)에 props를 전달할 수 있다.=>
    < 전달이름={전달하고픈이야기} >

  • 이벤트 핸들러 함수를 만들고 React에서 이용할 수 있다.=>
    확인!

  • 실제 웹 애플리케이션의 컴포넌트를 보고 어떤 데이터가 state이고 props에 적합한지 판단할 수 있다.=>
    props는 변하지 않고 전달받아야할 데이터에 state는 컴포넌트가 렌더링될때마다 변하는 데이터에!

  • 실제 웹 애플리케이션 개발 시 적합한 state와 props의 위치를 스스로 정할 수 있다.

  • React의 단방향 데이터 흐름(One-way data flow)에 대해 자신의 언어로 설명할 수 있다.=>
    데이터는 상위 컴포넌트에서 하위 컴포넌트로 props를 통해 전달할 수 있다. 하위 컴포넌트의 데이터를 상위 컴포넌트로 전달해주려면 상태 끌어올리기를 사용하자!

props

외부로 부터 전달받은 값, 변경함수

props의 특징

  • 컴포넌트의 속성을 의미

  • 부모 컴포넌트(상위 컴포넌트)로 부터 전달받은 값

  • 외부로부터 전달받은 변하지 않는 값

  • 읽기전용

  • 객체형태

How to use props

props를 사용하는 3단계 순서는 다음과 같다

  1. 하위 컴포넌트에 전달하고자 하는 값(data)와 속성을 정의한다.

  2. props를 이용하여 정의된 값과 속성을 전달한다.

  3. 전달받은 props를 렌더링한다.




위 단계에 맞추어 props를 사용하기 위해 우선 <Parent><Child>라는 컴포넌트를 선언하고,
<Parent> 컴포넌트 안에 <Child> 컴포넌트를 작성

function Parent() {
  return (
    <div className="parent">
      <h1>I'm the parent</h1>
      <Child /> // 응애 나 Child 컴포넌트
    </div>
  );
};

function Child() {
  return (
    <div className="child"></div>
  );
};

컴포넌트를 만들었으니 이제 전달하고자 하는 속성을 정의하자.

HTML에서 속성과 값을 할당하는 방법과 같음

<a href="www.codestates.com">Click me to visit Code States</a

React 에서 속성 및 값을 할당하는 방법도 이와 유사.
다만, 전달하고자 하는 값을 중괄호 {} 를 이용하여 감싸주기

<Child attribute={value} />

Example 1) Child 컴포넌트에 text속성 선언후 값 할당


<Child text={"I'm the eldest child"} />

이제 <Parent>컴포넌트에서 전달한 "I'm the eldest child"라는 문자열을 <Child> 컴포넌트에서 받아 보자

함수에 인자를 전달하듯이 React 컴포넌트에 props 를 전달하면 되고

이 props 가 필요한 모든 데이터를 가지고 오게 됨.

function Child(props) {
  return (
    <div className="child"></div>
  );
};

props를 전달 받았으니, 마지막으로 이 props 를 렌더링해보자.

props 를 렌더링하려면 JSX 안에 직접 불러서 사용하면 됨.

다만, props 는 객체라고 하였고

이 객체의 { key : value } 는 <Parent> 컴포넌트에서 정의한 { attribute : value } 의 형태를 띠게 됨.

따라서 JavaScript 에서 객체의 value 에 접근할 때 dot notation 을 사용하는 것과 동일하게

props 의 value 또한 dot notation 으로 접근할 수 있음.

아래와 같이 props.text를 JSX에 중괄호와 함께 작성하자.

function Child(props) {
  return (
    <div className="child">
      <p>{props.text}</p>
    </div>
  );
};
// props.text 속성만 쏙 가져옴

props.children

props 를 전달하는 또 다른 방법으로 여는 태그와 닫는 태그의 사이에 value 를 넣어 전달할 수 있음.

이 경우 props.children 을 이용하면 해당 value 에 접근하여 사용할 수 있음.

단 props.children 쓰면 붙은거 다 가져오는듯?

  function Parent() {
  return (
    <div className="parent">
        <h1>I'm the parent</h1>
        <Child>I'm the eldest child</Child> // 이 사이에 넣은 것들은 다 props.childen으로 가져옴
    </div>
  );
};

function Child(props) {
  return (
    <div className="child">
        <p>{props.children}</p>
    </div>
  );

Example) 미워도 다시한번

  import "./styles.css";

const App = () => {
  const itemOne = "React를";
  const itemTwo = "배우고 있습니다.";

  return (
    <div className="App">
    <Learn>{itemOne}</Learn> // itemOne을 Learn 컴포넌트로 props해줌
    <Learn>{itemTwo}</Learn>
    </div>
  );
};

const Learn = (props) => {

  return <div className="Learn">
    {props.children} // props 받음
  </div>;
};

export default App;

Example) 미워도 다시한번2

<Food chicken="KFC" pizza="Dominos" />

자식 컴포넌트에서는 기본적으로 아래와 같은 형태로 액세스하게 됩니다.
const Food = ( foodBrands ) => {
console.log(`좋아하는 치킨은 ${foodBrands.chicken} 입니다.`);
console.log(`좋아하는 피자는 ${foodBrands.pizza} 입니다.`);
};

이를 구조분해 할당을 이용하여 좀 더 직관적이고 가독성 높게 작성할 수 있습니다.
(* 주의할점은 기본적으로 전달하는 props의 키와 동일한 이름을 사용해야 한다는 것입니다.)
const Food = ( {chicken, pizza} ) => {
console.log(`좋아하는 치킨은 ${chicken} 입니다.`);
console.log(`좋아하는 피자는 ${pizza} 입니다.`);
};

state

컴포넌트 내에서 변할 수 있는 값, 즉 상태는 React state로 다뤄야 함.

State hook, useState

state를 다루는 방법중 하나로 useState라는 특별한 함수가 있음.

이를 사용하기 위해선 import {useState} from "react" 써 줘야함.

이후 useState를 컴포넌트 안에서 호출함. like stat 라는 변수를 선언하는 느낌적인 느낌적인 느낌.

일반적인 변수는 함수가 끝날때 사라지지만 state변수는 React에 의해 사라지지 않음.

Example) useState 문법 예시

function CheckboxExample() {
// 새로운 state 변수를 선언하고, 여기서는 이것을 isChecked 라 부르겠습니다.
 const [isChecked, setIsChecked] = useState(false);

구조분해할당으로 풀어쓰면

 const stateHookArray = useState(false); // 2번
 const isChecked = stateHookArray[0];
 const setIsChecked = stateHookArray[1];

수도코드는

 const [isChecked, setIsChecked] = useState(false);
  // const [state 저장 변수, state 갱신 함수] = useState(state 초기 값);

isChecked : state를 저장하는 변수
setIsChecked : state isChecked 를 변경하는 함수
useState : state hook
false : state 초기값

  • 이 state 변수에 저장된 값을 사용하려면 JSX 엘리먼트 안에 직접 불러서 사용하면 됨.

여기서는 isChecked 가 boolean 값을 가지기 때문에 true or false 여부에 따라 다른 결과가 보이도록 삼항연산자를 사용

<span>{isChecked ? "Checked!!" : "Unchecked"}</span>

State 갱신하기

function CheckboxExample() {
  const [isChecked, setIsChecked] = useState(false);

  const handleChecked = (event) => {
    setIsChecked(event.target.checked);
  };

  return (
    <div className="App">
      <input type="checkbox" checked={isChecked} onChange={handleChecked} />
      <span>{isChecked ? "Checked!!" : "Unchecked"}</span>
    </div>
  );
}

여기서 <input type에서 checked는 걍 속성임. handleChecked안에 e.target.checked에서 checked는 이벤트 객체안에 이미 포함되어 있는 checked임!

  • 나의 해석
  1. useState의 초기값은 false임.
  1. input type은 체크박스인데 그 체크박스가 바뀌면(onChange).
  1. handleChecked 함수 작동
  1. 그 내용은 setIsChecked 호출인거임.
  1. 호출 결과에 따라 기존 isChecked가 변경, 갱신됨.
  1. React는 새로운 isChecked 변수를 CheckboxExample 컴포넌트에 마지막으로 넘김

React의 이벤트 처리 문법

  • React 에서 이벤트는 소문자 대신 카멜 케이스(camelCase) 를 사용

  • JSX를 사용하여 문자열이 아닌 함수로 이벤트 처리 함수(이벤트 핸들러; Event handler)를 전달
    예를 들어 HTML에서 이벤트 처리 방식이 아래와 같다면,

<button onclick="handleEvent()">Event</button>

React의 이벤트 처리 방식은 아래와 같습니다. (중괄호 사용 , () 안씀)

<button onClick={handleEvent}>Event</button>

handleEvent() 하면 렌더링 될때 이미 실행되어 버리므로 함수를 전달하는게 아니라 그 결과값만 onClick에 전달해게 됨!

onChange

<input> <textarea> <select> 와 같은 폼(Form) 엘리먼트는 사용자의 입력값을 제어하는데 사용됨

React 에서는 이러한 변경될 수 있는 입력값을 일반적으로 컴포넌트의 state 로 관리하고 업데이트함

onChange 이벤트가 발생하면 e.target.value 를 통해 이벤트 객체에 담겨있는 input 값을 읽어올 수 있음.

컴포넌트 return 문 안의 input 태그에 value 와 onChange 를 넣어줌.

이때 onChange 는 input 의 텍스트가 바뀔 때 마다 발생하는 이벤트입니다.

이벤트가 발생하면 handleChange 함수가 작동하며

이벤트 객체에 담긴 input 값을 setState 를 통해 새로운 state 로 갱신합니다.

function NameForm() {
  const [name, setName] = useState("");

  const handleChange = (e) => {
    setName(e.target.value);
  }

  return (
    <div>
      <input type="text" value={name} onChange={handleChange}></input>
      <h1>{name}</h1>
    </div>
  )
};

onClick

onClick 이벤트는 말 그대로 사용자가 클릭이라는 행동을 하였을 때 발생하는 이벤트.

버튼이나 <a> tag 를 통한 링크 이동 등과 같이 주로 사용자의 행동에 따라 애플리케이션이 반응해야 할 때

자주 사용하는 이벤트입니다.

위의 onChange 예시에 버튼을 추가하여 버튼 클릭 시 input tag 에 입력한 이름이 alert을 통해 알림창이 팝업되도록 코드를 추가

// 함수 정의하기

return (
  <div>
	...
    <button onClick={() => alert(name)}>Button</button>
	...
  </div>
  );
};

// 함수 자체를 전달하기

const handleClick = () => {
  alert(name);
};

return (
  <div>
      ...
    <button onClick={handleClick}>Button</button>
      ...
  </div>
  );
};

위와 같이 onClick 이벤트에 alert(name) 함수를 바로 호출하면 컴포넌트가 렌더링될 때 함수 자체가 아닌 함수 호출의 결과가 onClick 에 적용됨.

때문에 버튼을 클릭할 때가 아닌, 컴포넌트가 렌더링될 때에 alert 이 실행되고 따라서

그 결과인 undefined (함수는 리턴값이 없을 때 undefined 를 반환합니다.) 가 onClick 에 적용되어

클릭했을 때 아무런 결과도 일어나지 않습니다.

따라서 onClick 이벤트에 함수를 전달할 때는 함수를 호출하는 것이 아니라 아래와 같이 리턴문 안에서 함수를 정의하거나 리턴문 외부에서 함수를 정의 후 이벤트에 함수 자체를 전달해야 함.

Controlled Component

React가 state를 통제할 수 있는 컴포넌트를 Controlled Component라고 함.

Example) 통제 예시

import "./styles.css";
import React, { useState } from "react";

export default function App() {
  const [username, setUsername] = useState("");
  const [msg, setMsg] = useState("");

  return (
    <div className="App">
      <div>{username}</div>
      <input
        type="text"
        value={username}
        onChange={(event) => setUsername(event.target.value)}
        placeholder="여기는 인풋입니다."
        className="tweetForm__input--username"
      ></input>
      <div>{msg}</div>
     
      <textarea
        placeholder="여기는 텍스트 영역입니다."
        className="tweetForm__input--message"
        onChange={(e) => {
          return setMsg(e.target.value)
        }}
        value={msg}
      ></textarea>
    </div>
  );
}

React 데이터 흐름

  • React의 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작함.

-> 조그만 컴포넌트를 만들자. -> 그리고 점차 상향식으로 앱을 만들자!

  • 데이터는 위에서 아래로 흐른다. 부모 컴포넌트에서 props 를 이용해 받을 수 있음.

-> 즉 데이터 흐름은 하향식 ( 단방향 데이터 흐름)

  • 또한 컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못함!
  • 모든 데이터를 상태로 둘 필요는 없음. 상태는 최소화하는 것이 가장 좋음...

부모로부터 props를 통해 전달되지 않으면 state가 아님!
시간이 지나도 변하지 않으면 state가 아님!
컴포넌트 안의 다른 state나 prop를 가지고 계산 가능하다면 states아님!

  • 상태가 특정 컴포넌트에서만 유의미하다면, 특정컴포넌트에만 두면 됨

만약 하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면 이 때에는 공통 소유 컴포넌트를 찾아 그 곳에 상태를 위치해야 함

즉, 두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통 부모 컴포넌트에 상태를 위치해야 함

profile
괴발개발자에서 개발자로 향해보자

0개의 댓글