반응형

React Key 값으로 index를 줘도 될까요?

저는 상황에따라 문제가 생길 것이라고 생각합니다. 오늘은 그 이유에 대해서 이야기해볼게요!

 

우선 React에서 map 메서드를 이용해서 컴포넌트를 render할 때 key값을 주어야 합니다.

그 이유는 효율적으로 컴포넌트를 render하기 위해서입니다!

 

key를 주어야 하는 이유

const myArr = ['a', 'b', 'c']

myArr.map((item) => {
	return <div>{item}</div>;
})

 

위의 코드처럼 배열이 존재하고 이것을 map 메서드를 통해서 render한다고 생각 해봅시다.

이렇게 했을 때 리액트는 에러를 발생시킵니다.

이 상태에서 key를 주지 않아도 동작은 합니다.

여기에서 추가적으로 a와 b 사이에 z 라는 글자가 들어오게 되면 어떤식으로 동작을 하게 될까요?

<div>a</div>
<div>b</div> --> <div>z</div> 
<div>c</div> --> <div>b</div>
	    +--> <div>c</div>

이런식으로 굉장히 비효율적으로 바뀝니다.

그렇다면 고유한 key값을 주게 된다면 어떻게 될까요?

<div>a</div>
+<div>z</div>
<div>b</div>
<div>c</div>

이렇게 바로 추가되는 것이 효율적인거 같죠? 고유한 key값을 주어야 변화에 대한 감지가 제대로 이루어져서 효율적으로 작동합니다.

key값으로 고유한 값만 주면 되는거면 map메서드의 두번째 인자인 Index를 줘도 되지 않을까요?

고유한 값을 쓰기 위해서 index를 key 값으로 주고, 이 코드는 영어단어가 나오고 영어단어 뜻을 옆에 input에 적는거라고 가정해봅시다.

function App() {
  const [myArr, setMyArr] = useState(['apple', 'banana', 'carrot']);
  return (
    <div className="App">
      {myArr.map((item, index) => {
        return (
        <div key={index}>
        INDEX 값: {index} 영어단어: {item} 뜻:
        <input type="text">
        </div>);
      })}
    </div>
  );
}

 

결과가 잘 나오네요! 코드를 좀 더 수정해볼까요? 

버튼을 누르면 중간에 'hello'라는 문자가 삽입되도록 작성해보겠습니다.

 

function App() {
  const [myArr, setMyArr] = useState(['apple', 'banana', 'carrot']);
  const addChar = () => { // 추가된 부분(z삽입)
    setMyArr([...myArr.slice(0,1), 'hello', ...myArr.slice(1,)]);
  }
  return (
    <div className="App">
      {myArr.map((item, index) => {
        return <div key={index}>INDEX 값: {index} 영어단어: {item} &nbsp;
        뜻:
        <input type="text"></input>
        </div>;
      })}
      
      <button onClick={() => {addChar()}}>삽입</button> // 추가된 부분
    </div>
  );
}

그리고 나서 제가 banana의 뜻을 적다가 z를 삽입하는 버튼을 눌러보겠습니다.

버튼 누르기 전

 

버튼 누른 후

여러분의 예상과 일치하신가요? 저는 처음에는 바나나라는 한글이 banana가 있는 div와 함께 이동할줄 알았습니다.

배열의 요소가 변경되었고 리액트는 고유한 key값을 이용해서 re-render를 하게됩니다.

하지만 원래 banana의 index(key)값은 1이었는데 현재 배열의 요소가 추가되면서 index(key)가 1인것은 hello라는 단어가 되었습니다.

리액트는 index(key)가 1인 요소에 바나나라는 글자가 써있었으니 re-render할때도 동일한 엘리먼트를 보여주려고 합니다.

 

그래서 지금과 같은 현상이 일어나게 된 것입니다.

 

어떤가요? index값을 key값으로 주게 되면 문제점이 생길 것 같지 않으신가요?

그러면 어떤 값을 key값으로 쓰면 좋을까요?

  • 요소의 키는 항상 고유해야합니다. 
  • 안정적이어야 합니다. 요소 재정렬, 시간이 지남에 따라 영향 받지 않아야 됩니다.
  • 예측이 가능해야합니다. 

이러한 것을 잘 지켜서 사용하시면 좋을 것 같네요! (ex) DB에서 불러온 사용자 정보의 id값 같은경우는 auto_increment도 되고 절대 겹칠리 없을 거 같네요.

 

 

* 잘못된 정보가 있다면 댓글로 바로 잡아주시길 바랍니다! 저도 공부중이라 많이 미흡한 점 죄송합니다.

 

반응형
반응형

웹팩 모듈 설치시에 Refusing to install package with name "webpack" under a package 오류가 났다.

npm init으로 패키지명을 정할 때 실수가 있었다.

 

이유: pakage.json의 name 값을  'webpack'이라고 하면 안됌.

 

해결 방안: pakage.json의 name을  'webpack'  -> 'webpackpractice'로 변경하고 다시 설치

반응형
반응형

안녕하세요 이번에는 상태관리를 위한 Context API를 이해해보는 시간을 가지려합니다 ㅎㅎ

 

Context API를 사용하기전의 상황)

- 만약에 컴포넌트 여기저기서 필요한 데이터가 있을때는 보통 App의 state에 넣어서 관리가 진행되었고

컴포넌트간의 교류는 props로 교류를 했습니다. 이런 방식은 유지보수 능력이 떨어집니다.

 

그래서 이런 상태를 관리하기 위한 라이브러리인 (리덕스,MobX등)이 생겼습니다.

하지만 리액트에서 v16.3업데이트가 진행된 후에는 Context API가 많이 개선되어서 라이브러리 없이도 가능하게되었습니다.

 

이거를 사용하게되면 좋은점에 대해서 알아볼까요?

 

현재 가지고 있는 컴포넌트를 그려보았습니다.(props로 데이터를 전달하는것도 그려보았습니다.)

기존 방식의 데이터전달

이렇게 상위컴포넌트에서 하위컴포넌트 몇개를 걸쳐서 제일 아래의 컴포넌트에게 전달이됩니다.

하지만 Context API를 사용하면 데이터가 어떻게 전달될까요?

한번 그려보았습니다.

 

Context API 사용한 상태관리

Context를 걸쳐서 바로 아래있는 컴포넌트에게 상태를 전달할 수 있게됩니다. 지금은 이렇게 작은 구조이지만 

구조가 점점 커지면 Context API의 효율이 점점 올라갈겁니다!

 

그러면 어떻게 사용하는지 예제를 통해서 같이 공부해볼까요?

우선 프로젝트를 만들어주시고 TextContext.js를 만들어주세요

 

TextContext.js)

 

import { createContext } from "react";

const TextContext = createContext({ text: "hello Context api" });

export default TextContext;

 

이런식으로 createContext를 react라이브러리로 부터 받아와서 만들 수 있습니다.

createContext() 이 괄호안의 값은 기본값을 설정하는 곳입니다. 저는 객체의 text값을 주었습니다.

그러면 이 값을 어떻게 사용하는지 볼까요?

Text.js를 만들어서 그곳에서 상태를 받아오겠습니다.

 

Text.js

import React from "react";
import TextContext from "./contexts/TextContext";

const Text = () => {
  return (
    <TextContext.Consumer>
      {(value) => <div>{value.text}</div>}
    </TextContext.Consumer>
  );
};

export default Text;

이렇게 TextContext 안의 Consumer라는 컴포넌트로 조회가 가능합니다.

App.js에서 불러와서 결과를 확인해보세요.

 

App.js

import React from "react";
import Text from "./Text";

function App() {
  return (
    <>
      <Text />
    </>
  );
}

export default App;

 

 

그러면 기본값이 아닌 값을 바꾸기 위해서는 어떻게 해야할까요?

Provider

Provider를 사용하면 Context value를 바꿀 수 있습니다. 위의 예제를 바꾸면

 

App.js

import React from "react";
import Text from "./Text";
import TextContext from "./contexts/TextContext";

function App() {
  return (
    <TextContext.Provider value={{ text: "Hello Provider!" }}>
      <>
        <Text />
      </>
    </TextContext.Provider>
  );
}

export default App;

 

이런식으로 Provider 의 value값을 바꿔주면 바뀐값이 나오게 됩니다. 결과가 잘 나오나요?

*Provider를 사용하고 value를 넣어주지 않으면 오류가 나니 조심하세요!

 

 

useContext

리액트 hooks 에서 Context API를 사용하는 방법은 useContext를 사용하면 됩니다.

저는 개인적으로 이것이 더 편합니다. 왜냐하면 코드가 깔끔해집니다.

한번 예시를 볼까요?

 

Text.js

import React, { useContext } from "react";
import TextContext from "./contexts/TextContext";

const Text = () => {
  const { text } = useContext(TextContext);
  return <div>{text}</div>;
};

export default Text;

 

 

어때요? 훨씬 간결하게 작성할 수 있지않나요?? 저는 개인적으로 useContext를 사용하는게 좋아보입니다. ㅎㅎ

 

잘못된 정보가 있다면 지적해주시기 바랍니다! 제가 공부한 내용을 블로그에 기술하면서 복습중입니다!감사합니다

 

 

반응형
반응형

React에서 Create-react-app으로 작업을 하는분들에게 바칩니다.

 

CRA로 작업중에 API key를 사용하는 일이 생겼을때 깃허브에 이것을 올리고 싶지 않으시죠?

 

 

1. 프로젝트 root폴더에  .env 파일을 만든다

 

2. .env 파일안에 APIKEY를 입력한다 

REACT_APP_API_KEY = 12354564988

이런 방식으로 입력해주시면  됩니다

 

꼭!!  REACT_APP_ 으로 시작하고 입력하셔야됩니다.

 

 

3. js파일에서 process.env.REACT_APP_API_KEY(자신이 정의한 이름)으로 불러온다

이제 js파일에서 process.env.REACT_APP_(이름) 으로 불러와서 사용하면 됩니다.

 

중요한점)

 

.env 파일을 만들어서 수정할때마다 react서버를 껐다가 켜야 반영이됩니다.

 

 

 

마지막으로 .gitignore 파일에다가

.env라고 입력해주시고 깃허브에 올리시면 됩니다 ㅎㅎ

 

 

반응형

+ Recent posts