whatisthis?

220313 [TIL] Today I Learned 💯 React.js 본문

WEB STUDY/REACT

220313 [TIL] Today I Learned 💯 React.js

thisisyjin 2022. 3. 13. 13:43

React.js 

 

 

선언형

코드를 예측 가능하고 디버그하기 쉽게 만들어줌.

 

컴포넌트 기반

다양한 형식의 데이터를 앱 안에서 손쉽게 전달할 수 있고, DOM과는 별개로 상태를 관리할 수 있음.

 

 

💡 웹팩(webpack)의 기능

- 쪼개진 js 파일을 html이 실행할수 있는 하나의 파일로 합쳐준다.

 

 

 


React 클래스 컴포넌트

 

 

HTML

<head>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
</head>

<body>
    <div id="root"></div>
    <script src="./like-button.js"></script>
    <script src="./ReactDOM.js"></script>
</body>

 

like-button.js

const e = React.createElement;

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return e("button", null, "like");
  }
}

 

클래스형 컴포넌트

 

- class 클래스명 extends React.Component {

 constructor(props) {

super(props);

}

>> 부모 클래스인 React.Component의 props 객체를 가져오는것임.

 

 

ReactDOM.js

ReactDOM.render(e(LikeButton), document.querySelector("#root"));

 

 

1/ element를 생성
React.createElement 메소드 사용


2/ reactDOM으로 렌더링함
ReactDOM.render(변수명, root);

📃 클래스 사용시

 

- 빈 element 만들고

- 클래스 선언하고

- 클래스 내 render()부분에

>  render() { return 변수명(태그명, props, 내용) }

- ReactDOM.render(변수명, root)

 

 

props는 객체 형식으로 ,로 구분해서 작성하면 됨.

 

예>

{onClick: () => {console.log('clicked')}, type = 'submit'}

 

** 속성명은 js문법대로 camelCase로 써준다.

html에선 onclick이지만, js에선 onClick

 

 

 

state

 

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      liked: false,
    };
  }
  render() {
    return e(
      "button",
      {
        onClick: () => {
          this.setState({ liked: true });
        },
        type: "submit",
      },
      "like"
    );
  }
}

 

클래스형 컴포넌트이므로

contructor() { } 블록 안에 state를 선언해준다.

클래스이므로 this가 붙어야한다.

 

반드시 어디서 값을 불러올때

this.state.liked << 이렇게 불러와야함.

 

단, setState함수 내에서는

this.setState( {liked: true} ) 이렇게 liked라고만 해줘도 된다.

 

 

 

+)

chrome 확장프로그램 react dev-tool 설치완료 :)

- 컴포넌트 단위로 확인 가능하다.

 

class LikeButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      liked: false,
    };
  }
  render() {
    return e(
      "button",
      {
        onClick: () => {
          if (this.state.liked === false) {
            this.setState({ liked: true });
          } else {
            this.setState({ liked: false });
          }
        },
        type: "submit",
      },
      this.state.liked === true ? "liked" : "like"
    );
  }
}

 

 

 


 

JSX

 

위 방법은 너무 복잡하고 보기 안좋으므로

JSX라는 문법으로 작성해보자.

 

 return e(
  "button",
  {
    onClick: () => {this.setState({ liked: true });
    },
    type: "submit",
  },
  this.state.liked === true ? "liked" : "like"
);

🔺 이렇게 보기 안좋았던 코드가

 

 

🔻 이렇게 html 태그형식으로 보기좋게! (JSX)

return (
      <button
        onClick={() => {
          this.setState({ liked: true });
        }}
      >
        {liked}
      </button>
    );

 

 

 

ReactDOM 부분도 이런식으로 작성해준다.

ReactDOM.render(<LikeButton />, document.querySelector("#root"));

 

 

 

단, JSX 문법을 웹브라우저가 해독을 못하기 때문에

자바스크립트 컴파일러인 Babel을 이용해줘야함!

<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

 

그리고, 컴포넌트를 담은 js파일에 type="text/babel"이라고 추가해준다.

<script src="./like-button.js" type="text/babel"></script>

 

 

 

JSX = JavaScript + XML로,

반드시 닫는태그 />를 해줘야함. 문법이 엄격.

 

JSX안에서 javascript를 쓰려면 { } 안에 넣어줘야함.

 

 

+ 참고

{} curly brackets
[] square brackets
() parentheses

 

Babel은 JSX 문법을 브라우저가 이해할 수 있게 (위에서 했던대로 createElement ~~) 바꿔준다.

 

 

 

💯 예제 - 구구단 게임 제작

 

- 클래스 컴포넌트 이용

- 한번 submit 할때마다 랜덤으로 문제의 숫자가 바뀜

- 정답이면 ? - 정답입니다 / 오답이면 ? - 틀렸습니다 를 표시하는 공간이 하단에 존재함.

- input의 value, result부분, 그리고 두 숫자를 state로 지정해 변하도록 조정 - setState

- 그 외 조건은 상동. (babel, react, reactdom 임포트하고, ReactDOM.render 부분) 

 

class GuGuDan extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      first: Math.ceil(Math.random() * 9),
      second: Math.ceil(Math.random() * 9),
      value: "",
      result: "",
    };
    this.onFormSubmit = e => {
      e.preventDefault();
      console.log(e);
      if (this.state.value == this.state.first * this.state.second) {
        this.setState({ result: "⭕정답입니다" });
      } else {
        this.setState({ result: "❌틀렸습니다" });
      }
      this.setState({ value: "" });
      this.setState({
        first: Math.ceil(Math.random() * 9),
        second: Math.ceil(Math.random() * 9),
      });
    };
  }
  render() {
    return (
      <div>
        <h1>💯구구단 게임💯</h1>
        <div>
          📃 {this.state.first} 곱하기 {this.state.second} 는?
        </div>
        <form onSubmit={this.onFormSubmit}>
          <input
            type="number"
            required
            placeholder="정답 입력"
            value={this.state.value}
            onChange={e => {
              this.setState({ value: e.target.value });
            }}
          />
          <button type="submit">입력</button>
        </form>
        <div>{this.state.result}</div>
      </div>
    );
  }
}

 

+) 참고 - 메모

 

input의 onChange함수는 코드가 짧아서 arrow function으로 바로 JSX 코드내 { }안에 적었고,
form의 onSubmit함수는 코드가 길어서 따로 GuGuDan클래스의 메소드로 선언해주었다.
(this.onFormSubmit 함수)

 

 

 

 

 

결과

 

 

 

++) 조금 수정한 것

 

 

class GuGuDan extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      first: Math.ceil(Math.random() * 9),
      second: Math.ceil(Math.random() * 9),
      value: "",
      result: "",
    };
  }

 onFormSubmit = e => {
    e.preventDefault();
    if (parseInt(this.state.value) === this.state.first * this.state.second) {
      this.setState({
        result: "⭕정답입니다",
        value: "",
        first: Math.ceil(Math.random() * 9),
        second: Math.ceil(Math.random() * 9),
      });
    } else {
      this.setState({ result: "❌틀렸습니다", value: "" });
    }
  };

  onInputChange = e => {
    this.setState({ value: e.target.value });
  };

  render() {
    return (
      <div>
        <h1>💯구구단 게임💯</h1>
        <div>
          📃 {this.state.first} 곱하기 {this.state.second} 는?
        </div>
        <form onSubmit={this.onFormSubmit}>
          <input
            type="number"
            required
            placeholder="정답 입력"
            value={this.state.value}
            onChange={this.onInputChange}
          />
          <button type="submit">입력</button>
        </form>
        <div>{this.state.result}</div>
      </div>
    );
  }
}

 

변경사항

1. 나는 constructor() {} 블록 안에 this.onFormSubmit을 선언했었는데,

이렇게 하지말고 그냥 클래스 메소드로 선언하자.

 

constructor 안에 있는 함수 = 클래스로 객체가 생성되었을때 실행되는 코드들임

 

그 아래에, 즉 render() 윗줄에다가

onFormSubmit으로 선언하고, (선언시 this. 필요없다.)

JSX안에서 사용할땐 (호출시) {this.onFormSubmit} 으로 this.를 붙여줘야함!

 

 

2. 왠만해선 JSX안에서 함수 직접 쓰지말고,

따로 뺴서 관리하자.!! 싶어서

onInputChange도 위로 빼서 따로 선언했다.

 

 

3. 정답일 때와 오답일 때 둘다 숫자가 재설정되도록 했었는데,

정답일때만 바뀌는게 맞는것 같아서 수정했다.

 

 

onFormSubmit = e => {
  e.preventDefault();
  if (parseInt(this.state.value) === this.state.first * this.state.second) {
    this.setState({ result: "⭕정답입니다" });
  } else {
    this.setState({ result: "❌틀렸습니다" });
  }
  this.setState({
    value: "",
    first: Math.ceil(Math.random() * 9),
    second: Math.ceil(Math.random() * 9),
  });
};

🔺수정 전

 

 

🔻수정 후 

onFormSubmit = e => {
   e.preventDefault();
   if (parseInt(this.state.value) === this.state.first * this.state.second) {
     this.setState({
       result: "⭕정답입니다",
       value: "",
       first: Math.ceil(Math.random() * 9),
       second: Math.ceil(Math.random() * 9),
     });
   } else {
     this.setState({ result: "❌틀렸습니다", value: "" });
   }
};

 

 

+++) 기능 추가 - 지난 정답 로그 보기

 

class GuGuDan extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      first: Math.ceil(Math.random() * 9),
      second: Math.ceil(Math.random() * 9),
      value: "",
      result: "",
      line: "",
    };
  }

  onFormSubmit = e => {
    e.preventDefault();
    if (parseInt(this.state.value) === this.state.first * this.state.second) {
      this.setState({
        result: "⭕정답입니다",
        value: "",
        first: Math.ceil(Math.random() * 9),
        second: Math.ceil(Math.random() * 9),
        line:
          this.state.first +
          "*" +
          this.state.second +
          "=" +
          this.state.first * this.state.second,
      });
    } else {
      this.setState({ result: "❌틀렸습니다", value: "" });
    }
  };

  onInputChange = e => {
    this.setState({ value: e.target.value });
  };

  render() {
    return (
      <div>
        <h1>💯구구단 게임💯</h1>
        <div>
          📃 {this.state.first} 곱하기 {this.state.second} 는?
        </div>
        <form onSubmit={this.onFormSubmit}>
          <input
            type="number"
            required
            placeholder="정답 입력"
            value={this.state.value}
            onChange={this.onInputChange}
          />
          <button type="submit">입력</button>
        </form>
        <span>LOG 🔎 {this.state.line}</span>
        <div>{this.state.result}</div>
      </div>
    );
  }
}

 

 

🔻 이부분을 잘 보자

// 정답이면

this.setState({
        result: "⭕정답입니다",
        value: "",
        first: Math.ceil(Math.random() * 9),
        second: Math.ceil(Math.random() * 9),
        line:
          this.state.first +
          "*" +
          this.state.second +
          "=" +
          this.state.first * this.state.second,
      });