Front-end/React

React 기초(배열)- AWS 풀스택 과정 39일차

awspspgh 2024. 9. 6. 18:17
목차
1. 배열
2. 느낀 점

 

1. 배열

◈ 이론

■ array 랜더링 시 key의 존재 유무에 따라
업데이트, 삭제, 추가 시 효율적으로 랜더링 됨.

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

 

■ useRef()로 컴포넌트 안의 변수 만들기
- 컴포넌트에서 특정 DOM을 선택할 때 사용
- 컴포넌트 안에서 조회, 수정을 할 수 있는 변수를 관리할 수 있음.

■ useRef()로 관린하는 변수는 값이 바뀐다고 하여 
컴포넌트가 재랜더링 되지 않음.

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

 

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

 

 

◈ 실습

- App.js

import './App.css';
import UserList from './component/UserList';
import StoreList from './component/StoreList';

function App() {
  return (
    <div className="App">
      { <UserList /> }
      <br />
      <hr />
      {/* 맛집 리스트 추가 */}
      {/* 월미당(쌀국수집) */}
      { <StoreList />}
    </div>
  );
}

export default App;

 

- CreateUser.jsx

=> username,email,onChange,onCreage을 변수로 받음 > name은 데이터의 이름, value는 화면에 표시되는 값, onChange는 input창이 입력할 때마다 정보를 저장하기 위해서 연결, onCreate는 button을 클릭할 때마다 배열에 정보를 넣기 위해서 연결함

import React from 'react';

const CreateUser = ({ username, email, onChange, onCreate }) => {
    // const { username, email, onChange, onCreate } = props;
    return (
        <div className='createName'>
            <input 
            type="text" 
            name='username' 
            placeholder='이름' 
            onChange={onChange}
            value={username}
            />
            <input 
            type="text" 
            name='email' 
            placeholder='이메일' 
            onChange={onChange}
            value={email}
            />
            <button onClick={onCreate}>create</button>
        </div>
    );
};

export default CreateUser;

 

- User.jsx

=>  user의 username과 email를 가져옴(username, email 대신에 props를 활용할 수 있음) > User 함수가 실행될 때 user의 id 값을 onRemove의 파라미터에 전달함(언제든지 X버튼을 눌러도 전달했던 id값을 onRemove함수에게 전달하여 실행함) > span 태그를 이용하여 active가 true인지 false인지 삼항연산자를 통해서 색깔을 변경함

 import React from 'react';

const User = ({ user, onRemove, onToggle }) => {
    // const user = props.user;
    return (
        <div className='user'>
            <h3>
                <span style={{
                    cursor: 'pointer',
                    color: user.active ? 'green' : 'black'
                }} onClick={() => onToggle(user.id)}> {user.username}</span>
                <span>({user.email})</span>
                {/* function으로 매개변수를 전달할 겨우 */}
                <button onClick={() => onRemove(user.id)}>X</button>
            </h3>
        </div>
    );
};

export default User;

 

- UserList.jsx

- nextId

=> useRef(n)를 nextId에 저장하여 input창에 입력된 값의 id가 n이 되도록 함

 

- onChange

=> useState는 계속 랜더링을 하기에 다른 input창을 입력하면 기존에 입력했던 input창의 데이터를 초기화됨 > 입력될 때마다 ...inputs로 기존의 값을 복사하고 key : value 형태인 [name] : value로 저장함(수정된 데이터만 업데이트되는 형식)

 

- onCreate

=> id : nextId.current로 id는 현재의 nextId라는 것을 정함(username과 email은 key와 value의 이름이 같은 경우이기에 value를 생략하여 적을 수 있음 (ex : username : username > username)) > concat을 이용하여 input창에 입력된 값을 배열에 저장함(추가되는 형식) > 기존 input창에 입력된 값을 초기화 > setUsers를 통해 id가 저장되었기에 nextId.current의 값을 +1를 해주어 다음 id로 생성될 수 있도록 세팅함

 

- onRemove

=> filter를 활용하여 파라미터를 받는 함수를 만듦 > User.jsx에 onRemove 버튼이 있기에 map을 실행할 때 onRemove를 연결함(filter는 조건에 부합한 원소만 추출함)

 

- onToggle

=> 삼항연산자를 통해 자신이 선택한 id가 같다면 active의 값를 반대로 바꾸고 id가 다르다면 기존의 값 그대로 setter 저장하며 setter가 useState로 저장되어있기에 기존의 값이 초기화가 됨 > spread를 통해서 기존의 값을 복사함

 

- return

=> key(=> id)값을 안 정해주면 console에서 오류가 나옴

 

import React, { useRef, useState } from 'react';
import User from './User';
import CreateUser from './CreateUser';

const UserList = () => {

    const nextId = useRef(6);

    const [users, setUsers] = useState([
        {
            id: 1,
            username: 'kim',
            email: 'kim123@naver.com',
            active: true
        },
        {
            id: 2,
            username: 'lee',
            email: 'lee123@naver.com',
            active: true
        },
        {
            id: 3,
            username: 'park',
            email: 'park123@naver.com',
            active: false
        },
        {
            id: 4,
            username: 'choi',
            email: 'choi123@naver.com',
            active: false
        },
        {
            id: 5,
            username: 'hong',
            email: 'hong123@naver.com',
            active: false
        }
    ]);
    
    const [ inputs, setInputs ] = useState({
        username : '',
        email : ''
    });

    // 구조 분해 할당 : 객체의 구조를 분해하여 변수에 할당하는 방법
    const { username, email } = inputs;
    
    const onChange = (e) => {
        const { name, value } = e.target;
        // 변경되지 않은 대상값을 공백처리 => 기존값 유지
        setInputs({
            ...inputs,  // 기존 inputs 값을 복사
            [name]:value  // 현재 변경된 값을 key : value 형태로 set
        });
        console.log(inputs);
    }

    const onCreate = ()=>{
        // 값이 추가되면...
        // 나중에 여기서 구현
        // .current : 현재값 
        const user = {
            id: nextId.current,
            username: username,
            email: email
        }
        // 현재 users에 user 추가 => concat
        setUsers(users.concat(user));

        // 기존 inputs 창 초기화
        setInputs({
            username:'',
            email:''
        })

        nextId.current += 1 ; //ref() : 재랜더링이 일어나지 않음
        console.log(users);
    
    }

    const onRemove = (id) => {
        // filter : 배열의 항목을 제거하기 위해서 사용
        // filter는 조건에 맞는 값만 배열로 리턴
        // user.id가 일치하지 않는 원소만 추출하여 새로운 배열로 리턴
        setUsers(users.filter(user => user.id !== id));
    }

    const onToggle = (id) => {
        // map : 배열의 처리를 하여 배열로 리턴
        // forEach : 배열의 처리만 하고 리턴하지 않음
        // user.id가 파라미터의 id와 일치하면 active의 상태를 반전시켜 줌.
        setUsers(users.map(u=>
            u.id === id ? { ...u, active: !u.active} : u
        ))
    }

    return (
        <div className='userList'>
            {/* 컴포넌트에서 데이터를 하위 컴포넌트에게 전달하는 방법 = props */}
            {/* {
                users.map(u=>(
                    <User user={u} key={u.id}/>
                ))
            } */}
            <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate}/>
            {
                users.map((u)=>(
                    <User user={u} key={u.id} onRemove={onRemove} onToggle={onToggle}/>
                ))
            }
        </div>
    );
};

export default UserList;

 

※ == 와 === 의 차이점

: `===`는 엄격한 동등 비교로, 타입과 값이 모두 같아야 참(true)입니다. `==`는 느슨한 동등 비교로, 타입이 다르면 자동으로 변환 후 비교합니다.

 

▷ 출력

출력 (1)

 

2. 느낀 점

오늘 수업을 들으면서 수업 내용을 거의 이해할 수 있어서 기뻤다. 오늘 배운 내용을 까먹지 않도록 주말에 복습을 해야겠다.