React

    [React] 리액트 초기 환경 세팅하기

    node 프로젝트를 생성(npm init)하고 기본적인 라이브러리들을 설치한다. npm i react @types/react npm i react-dom @types/react-dom npm i typescript npm i -D prettier eslint-plugin-prettier eslint-config-prettier ESLint와 prettier도 설치해주면 좋다. 사실 VSCode를 쓴다면 extensions만 설치해도 에디터가 다 잡아주기 때문에 node 모듈까지 굳이 설치할 필요는 없는 것 같다. 착각하기 쉬운데, 저장을 눌렀을 때 코드가 자동으로 정렬되고, 잘못된 코드에 밑줄이 그어지는 건 npm으로 설치하는 eslint와 prettier가 하는 게 아니다. 그건 vscode가 지원하는..

    [React] 왜 key는 list에서만 필요할까? 왜 index를 key로 사용하면 안되는 걸까?

    1 1 1 {[1, 1, 1].map(v => {v})} 위의 두 코드는 서로 같은 결과는 내는데, 아래의 코드는 react에서 경고를 뿜어낸다. 각 element가 고유한 key값을 가져야 한다는 것. 이 key를 넘겨줘야 하는 이유는 list의 각 요소에 대해 react에서 key를 임의로 부여하기 어렵기 때문이다. {[1, 1].map(v => {v})} 이 코드를 보자. 요소가 3개에서 2개로 줄었는데, 첫 번째가 사라진건지, 중간에 있던 게 사라진건지, 아니면 마지막 요소가 사라진건지 리액트 입장에서는 알 수 없다. 따라서 개발자가 정해줘야 하는 것이다. {[1, 1, 1].map((v, index) => {v})} 그렇다고 이렇게 index로 정해주면 안된다. 첫 번째 요소가 삭제되어도, 두 ..

    [React] React.FC, React.VFC를 쓰면 안되는 이유

    리액트와 타입스크립트를 사용할 때 FC와 VFC가 타입으로 쓰인다. VFC가 나오기 이전에 FC를 사용하는 걸 피해야 했던 이유는 크게 두가지가 있었다. FC가 props로 children을 옵셔널로 포함하고 있기 때문에 children이 필요하지 않은 컴포넌트에 children을 전달하는 경우 어떠한 오류도 발생하지 않는다. (엄격함을 지향하는 typescript와 모순되는 것처럼 보인다.) FC와 defaultProps를 동시에 사용하는 경우 제대로 작동하지 않음 근데 children을 없앤 VFC가 나오고, defaultProps가 deprecated 되면서(이전 글 참고) 위의 두 문제는 해결되는 것처럼 보였다. 왜 처럼이냐면 VFC 역시 사라지게 될(deprecated) 운명이기 때문.. 정확히..

    [React] 함수형 컴포넌트에서 defaultProps와 default parameters 중 무엇을 사용해야 할까?

    아래와 같이 defaultProps를 사용해서 props가 명시되지 않은 경우 기본값을 사용하게 할 수 있다 const Component = ({ prop1, prop2 }) => ( ); Component.defaultProps = { prop1: 'hello', prop2: 'world', }; ES6 문법에서, 아래와 같이 비구조화 할당을 이용해 default parameter를 지정해줄 수 있다. const Component = ({ prop1='hello', prop2='world' }) => ( ); 위 두 방법 모두 동일한 기능을 수행하는데, 두 번째 방법(default parameter)을 사용하는 걸 추천한다. defaultProps는 본래 클래스형 컴포넌트에서 사용되기 위해 만들어졌다...

    [React] props에 객체를 전달하면: pass by reference

    [React] props에 객체를 전달하면: pass by reference

    함수 파라미터로 객체를 넘기면 참조값이 전달됩니다. 마찬가지로 props에 객체를 전달하면 참조값이 전달됩니다. (배열 또한 객체이므로 동일) 예시) change를 누르고 print log를 누르면 777이 출력됩니다. 화면상의 숫자값은 당연히 변경되지 않습니다. +추가 리액트의 리렌더링 조건 중에 props가 바뀌는 경우가 있는데 myobj를 props로 넘기고 myobj = obj2; 로 myobj를 변경해도 리렌더링되지 않는다. 이는 애초에 App 컴포넌트가 리렌더링되지 않았기 때문이다.

    [React] 리액트 디자인 패턴에 대한 고찰

    [React] 리액트 디자인 패턴에 대한 고찰

    컴포넌트란? 재사용이 가능한 독립적인 모듈 단위 보통 컴포넌트를 말할 때 독립적이다. 재사용이 가능하다. 라고 말하지만 사실 그건 이상적인 컴포넌트의 모습일 뿐, 현실은 그렇게 간단하지 않습니다. 완벽하게 독립적인 컴포넌트는 무엇일까요? 아래의 Counter 컴포넌트를 봅시다. 사실 저는 이게 이상적인 컴포넌트의 모습이라고 생각합니다. 외부의 간섭 없이, 자기가 가지고 있는 것들로 할 일을 모두 수행합니다. 따라서 아래와 같이 정말로 레고를 조립하듯 간단하게 사용할 수 있습니다. 하지만 독립성이 컴포넌트가 추구해야할 모든 것은 아닙니다. 독립성은 확장성과 반비례하는데, 이는 재사용성과도 관련이 있습니다. 확장할 수 없다면 재사용할 수도 없기 때문에, 재사용이 가능한 독립적인 단위라는 설명은 사실 상반되는..

    [React Native] axios로 formData 전송이 안되는 문제

    보통 react native에서 axios로 formData를 보내려고 하면 아래와 같이 headers에 'content-type'을 'multipart/form-data'로 설정합니다. const body = new FormData(); body.append('email', 'test'); body.append('password', 'test'); const response = await myAxios.post('/auth/sign-up', body, { headers: { 'content-type': 'multipart/form-data' }, }); 하지만 서버측 처리에 따라 위와 같이 하는 경우 에러가 발생할 수 있습니다. axios가 formData를 전송할 때 문자열로 바꿔버리기 때문인데, t..

    [React] Closure와 초월자 useRef()

    [React] Closure와 초월자 useRef()

    최근에 타이머를 만들 일이 생겼습니다. setInterval()을 이용해 주기적으로 특정 함수를 호출할 수 있기 때문에 타이머를 구현할 때는 보통 이 함수를 사용합니다. const [time, setTime] = useState(0); useEffect(() => { const timer = setInterval(() => { console.log(time); setTime(time + 1); }, 1000); }, []) 처음에는 위와 같이 구현해봤습니다. 매초마다 time 값이 1씩 증가하는 것을 예상했으나 동작이 제대로 되지 않았습니다. 화면에는 0에서 1로 증가하더니 더이상 증가하지 않았고, 로그에는 계속 0만 찍히는 모습입니다. 그래서 코드를 아래와 같이 바꿔보았습니다. (setLocalTime..