본문 바로가기

React

리액트훅 useState에서 setState함수의 인자값에 대하여

요즘엔 컴포넌트방식이 아닌 Hook방식의 리액트가 표준으로 권장되고 있다.

 

그래서 기존에 MaterialUI같은 유명한 리액트 UI Framework들도 함수형으로 샘플코드를 바꾸었다.

 

이때 useState와 useEffect를 동시에 사용하는 방식으로 운용이 된다.

 

 

로딩 애니메이션을 넣어주는 코드이다.

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import CircularProgress from '@material-ui/core/CircularProgress';

const useStyles = makeStyles((theme) => ({
  root: {
    display: 'flex',
    '& > * + *': {
      marginLeft: theme.spacing(2),
    },
  },
}));

export default function CircularDeterminate() {
  const classes = useStyles();
  const [progress, setProgress] = React.useState(0);

  React.useEffect(() => {
    function tick() {
      // reset when reaching 100%
      setProgress((oldProgress) => (oldProgress >= 100 ? 0 : oldProgress + 1));
    }

    const timer = setInterval(tick, 20);
    return () => {
      clearInterval(timer);
    };
  }, []);

  return (
    <div className={classes.root}>
      <CircularProgress variant="determinate" value={progress} />
      <CircularProgress variant="determinate" value={progress} color="secondary" />
    </div>
  );
}

 

이런식으로 useState와 useEffect를 둘다 사용하여 기존에 컴포넌트 방식에서 하던 코드를 대체했다.

 

여기서 눈여겨 볼점은 저 setProgress 부분이다.

 

setProgress는 useState의 setState 부분인데, 이곳에 인자값은 보통 값이나 객체를 넣는다.

 

하지만 자바스크립트는 함수를 값처럼 사용할수 있기 때문에

 

저곳에 함수적 정의를 할 수가 있다.

 

함수적 정의를 하면 좋은점이, 여러번의 적용을 시킬 코드를 짤 경우 교체방식이라서 한번만 적용이 되는데

 

함수적 정의를 하면 순차적으로 여러번 적용이 정상적으로 된다.

 

setProgress안에 () => () 이런 형태의 인자값이 들어간다.

 

이건 익명함수를 표현한 것이다.

 

익명함수를 사용하는 이유는 굳이 이것을 모듈화하거나 외부로 뺄 필요없이

 

한번만 사용이 될 로직이기 때문에 굳이 이름도 붙여주지 않고, 1번만 사용하는거라고 이해하면 편하다.

 

즉 저런식의 코드는 이런식으로도 대체가 가능하다.

 

function tick() {
      // reset when reaching 100%
      setProgress(
        /* 이런식의 익명함수를 보기 좋게 쓰면 밑에것처럼 되는 것이다. 첫번째 ()는 파라미터, 두번째 ()는 함수식과 리턴값 자체를 의미한다. */
        function(들어간놈){
          return 들어간놈 >= 100 ? 0 : 들어간놈 + 1
        } 
        /* (들어간놈) => (들어간놈 >= 100 ? 0 : 들어간놈 + 1) */
      );
    }

 

일부러 파라미터의 값을 한글로 써버렸다.

 

보통 저런 파라미터 자리에 의미상 통하는 변수를 네이밍하는데,

 

처음보는 사람은 그 이름이 무슨 기능을 해주는게 아닌가 헷갈릴수도 있다.

 

(oldProgress) => (oldProgress + 1)

 

이런식으로 쓰여 있으니 뭔가 있는것 같은데 저 'oldProgress'나 '들어간놈'이나

 

어차피 똑같이 작동하게 된다.

 

 

저 로직을 만약 바꿔야할 일이 생길것 같다면 외부함수로 빼내어 저 자리에 함수를 넣어도 된다.

 

 

주의점은 () => ()  이런 표현은 '리턴값이 있는 익명함수' 라는것을 기억해야 한다.

 

두번쨰 ()에 함수의 구현 내용과 리턴을 뭘 어떻게 하는지까지 포함해서 들어가 있다고 생각하면 된다.

 

 

알면 쉬운데, 모를땐 정말 헷갈리기 딱좋게 생겨서 멘붕을 겪곤하는것 같다.