React: state(데이터 저장)

summereuna🐥·2021년 11월 11일
0

React JS

목록 보기
3/69

React의 state

질문

어떻게 하면 React 어플에 값이 바뀔 데이터를 담아줄 수 있을까?


state: 기본적으로 데이터가 저장되는 곳

현재 우리는 counter를 증가시켜서 UI(user interface)에 display하고 있다.
이 counter의 바뀌는 데이터를 state로 만들 수 있다.

작성하기

bad way 1

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    let counter = 0;
    //🔥이런 변수들을 JSX에 전달하는 방법👉 {} 중괄호를 쓴다.
    function countUp() {
      counter = counter + 1;
      ReactDOM.render(<Container />, root);
    }
    const Container = () => (
      <div>
        //🔥JSX에 변수 전달하는 방법: {변수}
        <h3>Total clicks: {counter}</h3>
        <button onClick={countUp}>Click me</button>
      </div>
    );
    ReactDOM.render(<Container />, root);
  </script>
</html>

코드 설명

  • 어플리케이션이 시작될 때, 23번째 줄에서 Container를 렌더링한다.
  • 그리고 버튼을 클릭하면 counter에 계속 1씩 추가는 되는데, 그것을 ui로 렌더링하지는 못한다.
  • 그렇기 때문에 countUp()함수에 아에 렌더링하는 것을 추가하여 ui에 표시되게 해야 한다.
    즉, 데이터가 바뀔 때마다, container를 리렌더링해줘야 한다.
  • 리랜더링하면 다시 Container 함수를 실행하기 때문에 버튼을 클릭할 때 마다 리랜더링 되어서 ui에 잘 출력되는 것이다.

bad way 2

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    
    let counter = 0;
    
    function countUp() {
      counter = counter + 1;
      //🔥
      render();
    }
    
    //🔥아에 렌더 함수를 만들어서 갖다 붙이기
    function render() {
      ReactDOM.render(<Container />, root);
    }
    
    const Container = () => {
    return (
      <div>
        <h3>Total clicks: {counter}</h3>
        <button onClick={countUp}>Click me</button>
      </div>
     );
    }
    
    //🔥
    render();
  </script>
</html>

코드 설명

아에 렌더 함수를 만들어서 갖다 붙였다.

그나저나 이 방식은 데이터가 바뀔때 마다 render()함수를 호출하는 것을 잊으면 안되기 때문에 최고의 방법은 아니다.
폼이나 로그인페이지, 알림 등등이 있는데 이것을 계속 호출해야 한다면 돌아버릴거다..^^;;;

어쨌든 여기서 핵심 포인트는 바로 이거다!

🍦vanilla vs ❄️react

  • vanilla
    바닐라 자바스크립트에서 버튼을 클릭하면 해당하는 태그의 모든 부분을 업데이트한다.

  • react
    그런데 리액트에서는 UI에서 딱 바뀐 부분만 업데이트 해준다.

🔥 이처럼 리액트의 가장 큰 장점은, 업데이트가 필요한 부분만 업데이트를 할 수 있다는 점이다.
즉, interactive한 어플리케이션을 만들 수 있다는 뜻!
여러가지 요소들을 리렌더링하려고 해도, 전부다 새로 생성되는 것이 아닌, 오직 업데이트한 부분만 리렌더링된다.

best way

#3.1 setState part One

리렌더링을 발생시킬 가장 좋은 방법은 무엇일까?
데이터를 바꾸고 다시 렌더링 해주는 거다.
즉, 리렌더링하면 컴포넌트도 바뀐 데이터를 가지고 재생성되도록 만들어 주면 된다.

함수를 가져다 쓰는 대신 리액트에서 데이터를 보관하고 자동으로 리랜더링을 일으킬 수 있는 최고의 방법을 알아보자.

React.useState()

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      //리액트가 가진 기능을 활용하여 리랜더링 시켜 보자!
      //1. 함수 내에서 return문 전에 상수를 하나 만들고,
      const data = React.useState();
      //2.콘솔에 찍어보자.
      console.log(data);
      return (
        <div>
          <h3>Total clicks: 0</h3>
          <button>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

console.log(data);를 해보면 undefined 과 함수를 가진 배열이 뜨는 것을 확인할 수 있다. React.js가 const data = React.useState(); 이 코드를 가지고, 우리가 위에서 했던 많은 것들을 제공해 주고 있다는 뜻이다!

이 코드로 우리가 얻는 건 [undefined, 함수]이다.
이것은 [data, data 값을 바꿀 수 있는 함수] 이기 때문에, undefined이 data이고 뒤의 함수는 data를 바꿀때 사용하는 함수이다.

React.useState()함수는 초기값을 설정할 수 있다.

초기값을 0으로 설정해 보자.

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      const data = React.useState(0);
      console.log(data);
      return (
        <div>
          <h3>Total clicks: 0</h3>
          <button>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

그러면 data를 콘솔로그 했을 때, [0, f]가 뜬다.
배열의 첫 번째 값은 초기값이고, 두번째 값인 함수는 배열의 첫 번째 값을 바꾸는 함수이다.

결론적으로 React.useState()**는 전에 만들었던 함수의 역할을 대신한다.

전에 만들었던 함수

let counter = 0;

function countUp() {
  counter = counter + 1;
  render();
}

data 값에 접근하기 쉽게 코드 수정

그런데 배열상태 그대로 사용하는건 보기 불편하다.
data에 접근하려면 data[0]이라고 적어줘야 배열의 첫번째 값인 데이터 값을 가져다 쓸 수 있으니..

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      const data = React.useState(0);
      return (
        <div>
          <h3>Total clicks: {data[0]}</h3> //👈
          <button>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

그래서 JS가 가진 아주 짧지만 멋진 코드로 보다 쉽게 배열의 첫 번째 값을 가져와 보자 ^^!
어떻게 배열에서 요소들을 꺼내서 이름을 부여할 수 있을까?

전통적인 방법

//이렇게 어레이에 요소가 담겨 있다면
const food = ["tomato", "potato"]
//그 요소들을 꺼내서 쓰기 위해서는 보통은 이렇게 접근한다.
const tomato = food[0]
const potato = food[1]

이런식으로 한다면

const root = document.getElementById("root");
const App = () => {
  const data = React.useState(0);
  const counter = data[0]; //👈
  const modifier = data[1]; //👈
  return (
    <div>
    	<h3>Total clicks: {counter}</h3>
		<button>Click me</button>
	</div>
	);
};
ReactDOM.render(<App />, root);

이런식으로 쓸 수 있겠다.
하지만 ㅎ..ㅎ 굳이..!! 더 효율적인 방법을 찾아보자 우린 게으르니깐..!

더 좋은 방법 = 숏컷!!

//이렇게 어레이에 요소가 담겨 있다면
const food = ["tomato", "potato"]
//각각의 요소에 이름을 할당해 주고 그 이름을 사용할 수 있다. <어우..이거 wetube 배울 때 ES6 그거 아니냐
const [myFavFood, mySecondFavFood] = food

그러면 myFavFood를 입력하면 tomato가 뜨고
mySecondFavFood를 입력하면 potato가 뜬다.

이런식으로 한다면

const root = document.getElementById("root");
const App = () => {
  const [counter, modifier] = React.useState(0); //🔥👈
  return (
    <div>
    	<h3>Total clicks: {counter}</h3>
		<button>Click me</button>
	</div>
	);
};
ReactDOM.render(<App />, root);

걍 counter에 값 주면 안되냐.. 왜 모디파이어가 필요한가?

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      let [counter, modifier] = React.useState(0);
      //핸들러
      const onClick = () => {
        counter = counter + 1;
        console.log(counter);
      };
      return (
        <div>
          <h3>Total clicks: {counter}</h3>
          //온클릭 이벤트 발생시 onClick 핸들러 작동하게
          <button onClick={onClick}>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

버튼 클릭하면 onClick 핸들러가 발생하기 때문에 콘솔에 계속 +1 씩 찍히지만, 저번 처럼 화면상에 출력은 안된다.
이 때 필요한 것이 바로 우리의 modifier!!!
🔥 modifier에 값을 부여하면 modifier 함수는 그 값으로 업데이트하고 리렌더링을 일으킨다!
직접 랜더링 해줄 필요가 없다는 사실 ^3^!

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      const [counter, modifier] = React.useState(0);
      const onClick = () => {
     //🔥modifier에 값을 부여하면 modifier 함수는 그 값으로 업데이트하고 리렌더링을 일으킨다!!!
        modifier(counter + 1);
      };
      return (
        <div>
          <h3>Total clicks: {counter}</h3>
          <button onClick={onClick}>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

보통은 [counter, setCounter] 이런식으로 이름을 붙여 준다.

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    const App = () => {
      const [counter, modifier] = React.useState(0);
      const onClick = () => {
     //🔥modifier에 값을 부여하면 modifier 함수는 그 값으로 업데이트하고 리렌더링을 일으킨다!!!
        modifier(counter + 1);
      };
      return (
        <div>
          <h3>Total clicks: {counter}</h3>
          <button onClick={onClick}>Click me</button>
        </div>
      );
    };
    ReactDOM.render(<App />, root);
  </script>
</html>

React.js가 제공하는 중점적인 부분!
data가 바뀔때마다 component를 리렌더링하고 UI를 refresh한다!
즉, modifier함수로 state를 바꿀 때, 컴포넌트 전체가 새로운 값을 가지고 재생성된다.

profile
Always have hope🍀 & constant passion🔥

0개의 댓글