프론트엔드/React

React 배열(array) 및 훅(Hook)

짱뚱짱 2024. 9. 6. 18:06

🟢 리액트는 효율적으로 컴포넌트를 렌더링하고 관리하는 것이 중요 => 설계가 중요하다.

📢배열에서 key

👉🏻 리액트에서 배열(array)을 렌더링할 때, 각 항목에 고유한 key를 설정.

👉🏻 key는 배열이 업데이트, 삭제 또는 추가될 때 효율적인 렌더링을 가능하게 함. => key를 이용해 어떤 항목이 변경, 추가 또는 제거되었는지 빠르게 인식

users.map((u,i)=>(
    <User user={u} key={i}/>
))

🟢 key가 없으면 리액트는 배열 항목의 변경 사항을 제대로 추적X => 성능 저하.

    - 배열을 렌더링할 때는 항상 고유한 key를 지정

 

📢useRef()

👉🏻 useRef()로 컴포넌트 안의 변수 만들기

    - 컴포넌트에서 특정 DOM을 선택할 때 사용
    - 컴포넌트 안에서 조회, 수정을 할 수 있는 변수를 관리할 수 있음.

👉🏻 useRef()로 관리하는 변수는 값이 바뀐다고 하여 컴포넌트가 재렌더링 되지 않음
    - useState보다 좀 더 효율적이다. 

👉🏻 useRef()를 통해 관리하는 값들

    - setTimeout / setInterval을 통해서 만들어지는 id
    - 조회, 수정, 삭제 시 사용되는 id
    - 외부 라이브러리를 사용하여 생성된 인스턴스

📢useRef()  vs  useState()

👉🏻 비슷하게 어떤 값을 저장하는 저장공간의 역할
👉🏻 컴포넌트 안에서 조회 및 수정할 수 있는 변수를 관리
👉🏻 useRef()로 관리하는 변수는 값이 바뀐다고 해도 컴포넌트가 재렌더링 되지 않음.
👉🏻 state : 변화 => 렌더링 => 컴포넌트 내부 변수들 초기화
👉🏻 ref : 변화 => 렌더링X => 내부 변수들 값 유지
    => 변경시 렌더링을 발생시키지 말아야 하는 값을 다룰 때 사용
    => 변화는 감지해야 하지만, 그 변화가 렌더링을 발생시키지 않아야 할 때 사용

📢실습

npx create-react-app list-app 명령어로 새로운 앱을 생성하여, 맛집 리스트 관리.

컴포넌트명 : Store.jsx / StoreList.jsx / CreateStore.jsx

 

App.js

import './App.css';
import StoreList from './components/StoreList';

function App() {
  return (
    <div className="App">
      {/* 맛집 리스트 추가 두 개 정도만 미리 추가해 놓고, 추가할 수 있게 버튼 만들기. id, storeName, detail*/}
      {/* 월미당(쌀국수집) */}
      <StoreList />
    </div>
  );
}

export default App;

 

 

components/StoreList.jsx

import React, { useRef, useState } from 'react';
import CreateStore from './CreateStore';
import Store from './Store';

const StoreList = () => {
    const nextId = useRef(3);

    const [stores, setStore] = useState([
        {
            id: 1,
            store: '월미당',
            storeItem: '쌀국수'
        },
        {
            id: 2,
            store: '두리네',
            storeItem: '베이글샌드위치'
        }
    ]);

    const [inputs, setInputs] = useState({
        store: '',
        storeItem: ''
    })

    const {store, storeItem} = inputs;

    const onChange = (e) => {
        const { name, value } = e.target;
        setInputs({
            ...inputs,
            [name]:value
        })
    }

    const onCreate = ()=>{
        //값이 추가되면....
        //나중에 여기서 구현.
        const storeD = {
            id: nextId.current,
            store,
            storeItem
        };
        setStore(stores.concat(storeD));
        setInputs({
            store:'',
            storeItem:''
        })
        nextId.current += 1;
    }

    const onRemove=(id) =>{
        setStore(stores.filter(store => store.id !== id))
    }

    return (
        <div className='storeList'>
            <CreateStore 
                store={store} 
                storeItem={storeItem}
                onChange={onChange}
                onCreate={onCreate}
            />
            {
                stores.map(s=>(
                    <Store store={s} key={s.id} onRemove={onRemove} />
                ))
            }

        </div>
    );
};

export default StoreList;

 

 

components/Store.jsx

import React from 'react';

const Store = ({ store, onRemove }) => {
    // const store = props.store;
    return (
        <div className='store'>
            <h3>
                {store.store}({store.storeItem})
                <button onClick={()=>onRemove(store.id)}>X</button>
            </h3>
        </div>
    );
};

export default Store;

 

 

components/CreateStore.jsx

import React from 'react';

const CreateStore = ({ store, storeItem, onChange, onCreate }) => {
    return (
        <div className='createStore'>
            <input 
                type="text"
                name='store'
                placeholder='가게명'
                onChange={onChange}
                value={store} 
            />
            <input 
                type="text"
                name='storeItem'
                placeholder='대표 메뉴'
                onChange={onChange}
                value={storeItem} 
            />
            <button onClick={onCreate}>create</button>
        </div>
    );
};

export default CreateStore;

 

결과