React-Props,State,Event

이수현·2022년 5월 24일
0

React

목록 보기
2/4

📚Props,State,Event

Props

Props: props는 React 컴포넌트에 전달되는 인수이다.

  • props는 태그의 속성을 통해 컴포넌트에 전달된다.
  • props는 읽기 전용이다.
function PropTest(props) {
  console.log(props);
  return <h1>{props.name}님 반갑습니다!</h1>;
}

export default PropTest;
-----------------------------------------------
import "./App.css";
import PropTest from "./PropTest";
function App() {
  return <PropTest name="suhyeon" age="28" />;
}

export default App;

console창에 props객체를 찍었을 때, name, age 프로퍼티가 있는 객체가 출력되는 것을 확인할 수 있다.

  • props객체에는 부모 컴포넌트에서 전달한 인자가 객체의 프로터티 키와 값으로 묶여 객체로 전달되는 것이다.(개인적인 이해)
  • 부모 컴포넌트에서 전달하는 인자는 객체 및 배열타입의 값도 전달이 가능하다. 아래 예시를 보자.
function PropTest(props) {
  console.log(props);
  console.log("props.userInfo", props.userInfo[0]);
  return <h1>{props.userInfo[0]["name"]}님 반갑습니다!</h1>;
}

export default PropTest;

--------------------------------------------
import "./App.css";
import PropTest from "./PropTest";
function App() {
  return <PropTest userInfo={[{ name: "suhyeon", age: "28" }]} />;
}

export default App;

  • 예시로 배열을 전달해봤지만 객체도 전달이 가능하다.

State && Event

React 엘리먼트에서 이벤트를 처리하는 방식은 기존 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사하다. 몇 가지 문법 차이는 다음과 같다.

  • React의 이벤트는 소문자 대신 camelCase를 사용한다.
  • JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달한다.
  • React에서 지원하는 이벤트 api목록은 https://ko.reactjs.org/docs/events.html에서 필요할 때 찾아서 사용하면 될 것 같다.
// HTML 방식
<button onclick="activateLasers()">
  Activate Lasers
</button>
----------------------------------
// React 방식
<button onClick={activateLasers}>
  Activate Lasers
</button>

stateprops와 마찬가지로 일반 javascript 객체이다. 두 객체 모두 렌더링 결과물에 영향을 주는 정보를 갖고 있는데, 한 가지 중요한 방식에서 차이가 있다.

  • props는 마치 함수 매개변수처럼 컴포넌트에 전달되는 반면 state는 함수 내에 선언된 변수처럼 컴포넌트 안에서 관리된다.

state 사용법


Returns a stateful value, and a function to update it.

  • 위 사진을 보면 useState()를 호출하면 반환되는 값이 [S, setStatckAction<S>]이 반환되는 것을 확인할 수 있다.
    => 첫 번째 원소인 S는 현재 상태값을 나타내고, 두 번째 원소인 setStackAction<S>는 상태를 설정하는 메서드를 나타낸다.
  • 그래서 보통 사용할 때 let [name, setName] = useState("suhyeon"); 처럼 사용한다.
    => useState()안에 있는 "suhyeon"은 name(=state)의 초기값이다.
  • 다음 예제 코드를 보며 이해해보자.
import { useState } from "react";
import "./App.css";
import PropTest from "./PropTest";
function App() {
  let [myName, setMyName] = useState("suhyeon");
  return <PropTest userInfo={[{ name: myName, age: "28" }]} />;
}

export default App;

------------------------------------
function PropTest(props) {
  console.log(props);
  console.log("props.userInfo", props.userInfo[0]);
  return <h1>{props.userInfo[0]["name"]}님 반갑습니다!</h1>;
}

export default PropTest;

위 코드에서 let [myName, setMyName] = useState("suhyeon");로 상태의 초기값을 "suhyeon"으로 설정하고, myName이라는 상태값을 PropTest 컴포넌트의 props로 넘겨주었는데 문제없이 나오는 것을 볼 수 있다.

  • 다음은 버튼을 한 개 만들어서 버튼을 클릭하면 색이 변하도록 만들어보자.
import { useState } from "react";
import "./App.css";
import PropTest from "./PropTest";
function App() {
  let [myName, setMyName] = useState("suhyeon");
  let [textColor, setTextColor] = useState("red");

  const changeColor = () => {
    textColor === "red" ? setTextColor("blue") : setTextColor("red");
  };
  return (
    <>
      <PropTest userInfo={[{ name: myName, age: "28" }]} color={textColor} />
      <button onClick={changeColor}>Change Color</button>
    </>
  );
}

export default App;

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

function PropTest(props) {
  console.log(props);
  console.log("props.userInfo", props.userInfo[0]);
  return (
    <h1 style={{ color: props.color }}>
      {props.userInfo[0]["name"]}님 반갑습니다!
    </h1>
  );
}

export default PropTest;

  • 위 코드를 보면 button 태그에 onClick이벤트를 부여해서 클릭할 때
    textColor === "red" ? setTextColor("blue") : setTextColor("red"); 삼항 연산자를 사용해서 현자 textColor 상태값이 red이면 blue로 red가 아니면 red로 상태값을 업데이트 해주도록 작성했다.
  • App컴포넌트의 상태값이 PropTest컴포넌트의 props로 전달되어 사용되는 것을 확인할 수 있다.

그렇다면 PropTest컴포넌트에서 App컴포넌트의 상태값을 변경할 수 없는지 알아보자.

import { useState } from "react";
import "./App.css";
import PropTest from "./PropTest";
function App() {
  let [myName, setMyName] = useState("suhyeon");
  let [textColor, setTextColor] = useState("green");

  const changeColor = (color) => {
    textColor === "green" ? setTextColor(color) : setTextColor("green");
  };
  return (
    <>
      <PropTest
        userInfo={[{ name: myName, age: "28" }]}
        color={textColor}
        clickEvent={changeColor}
      />
    </>
  );
}

export default App;
--------------------------------------------------
function PropTest(props) {
  console.log(props);
  console.log("props.userInfo", props.userInfo[0]);

  return (
    <>
      <h1 style={{ color: props.color }}>
        {props.userInfo[0]["name"]}님 반갑습니다!
      </h1>

      <button onClick={() => props.clickEvent("yellow")}>Change Color</button>
    </>
  );
}

export default PropTest;

  • 위 코드를 작성하면서 부모 컴포넌트에서 자식 컴포넌트로 state를 변경하는 함수를 props로 보내준다는 것 까지 생각을 하는건 어렵지 않았다.
  • 그런데 PropsTest컴포넌트에서 button 태그의 onClick 이벤트에 <button onClick={props.clickEvent("yellow")}>Change Color</button>로 코드를 작성하면 아래의 영상같이 계속 리렌더링되는 현상이 발생했다.

    => 콘솔창에는 다음과 같은 에러코드가 출력됐다. Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate.

    => 여기서 Maximum update depth exceeded. 발생하는 이유는 단순히 함수를 props.clickEvent("yellow")로 호출하는 것은 다음과 같은 루틴이 생긴다

    => (함수를 부른다 => render를 다시한다 => 또 함수를 부른다)가 반복되는 것이다.

    => 여기서 함수를 부른다는 것은 jsx문법인 {}안에 함수명()로 썼기때문에 바로 호출의 의미가 되는 것이다.

    => 그렇기때문에 () => this._toggleState(param)로 작성해야 반복이 발생하지 않는다.

    => 만약 매개변수가 없는 함수같은 경우는 onClick={함수명} 처럼 ()를 빼고 적어주면 된다.

마지막으로..

공식문서에 어떤게 state가 되어야 하는지 살펴보는 부분이 있는데, 나름 이해가 잘 되는 것 같아서 블로그에도 작성을 하려고 한다...

  1. 부모 컴포넌트로부터 props를 통해 전달이 되나요? 그러면 state가 아니다.
  2. 시간이 지나도 변하지 않나요? 그러면 state가 아니다.
  3. 컴포넌트 안의 다른 state나 props를 갖고 계산이 가능한가?? 그러면 state가 아니다.

앞으로 연습할 때 위 3가지를 염두해두고 state를 설정하는 연습을 해야겠다..

0개의 댓글