React : 배열 렌더링, useRef

김가영·2020년 12월 20일
0

Web

목록 보기
8/11
post-thumbnail

https://react.vlpt.us/basic/09-multiple-inputs.html 참고

배열 렌더링

map을 이용하기

배열 렌더링 때에는 key가 존재해야 한다. 중복되는 key 가 있으면 오류메세지가 생기며 업데이트가 안됨

배열의 index를 key 값으로 사용하기

import React from 'react'

function User({ user }) {
    return (
        <div>
            <b>{user.username}</b> <span>({user.email})</span>
        </div>
    )
}

function UserList() {
    const users =[
        {
            id: 1,
            username: 'velopert',
            email: 'public.velopert@gmail.com'
        },
        {
            id: 2,
            username: 'tester',
            email: 'tester@gmail.com'
        },
        {
            id: 3,
            username: 'liza',
            email: 'liz@gmail.com'
        },
    ]
    return (
        <div>
            {users.map((user, index)=> (
                <User user={user} key={index}/>
            ))}
        </div>
    );
}

export default UserList

또는 배열 내에 존재하는 값으로 key 값 설정하기

import React from 'react'

function User({ user }) {
   ...
}

function UserList() {
    ...
    return (
        <div>
            {users.map(user=> (
                <User user={user} key={user.id}/>
            ))}
        </div>
    );
}

export default UserList

useRef

DOM을 직접 선택하여 가져와야할 때
ex 특정 element의 크기를 가져오거나, 스크롤바 위치를 가져오거나, 설정하거나, 포커스를 설정하거나...

→ ref 를 이용한다
함수형 component에서 ref를 사용할 때에는 useRef라는 Hook 함수를 사용한다.

초기화를 눌렀을 때 이름 input에 포커스가 잡히도록

import React, {useState, useRef} from 'react';

function InputSample() {

    const [inputs, setInputs] = useState({
        name : '',
        nickname: ''
    });

    const nameInput = useRef();

    const {name, nickname} = inputs;

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

        })

    }
    const onReset = (e) => {
        setInputs({
            name : '',
            nickname : '',
        })
        nameInput.current.focus();
    }
    

    return (
        <div>
            <input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput}/>
            <input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname}/>
            <div>
                <b>값: </b>
            {name}({nickname})
            </div>
            <button onClick={onReset}>초기화</button>
        </div>

    )
}

export default InputSample;

useRef로 Ref객체를 만들고, 이 객체를 원하는 DOM에 ref 값으로 설정
→ Ref 객체의 .current 값은 원하는 DOM을 가리키게 됨

useRef로 component 내 변수 만들기

useRef를 DOM 을 선택하는 것 이외에도, component 내에서 조회 및 수정할 수 있는 변수를 관리하는 용도로 쓸 수도 있다.

다음과 같은 값을 관리할 수 있다

  • setTimeout, setInterval 을 통해 만들어진 id
  • 외부 라이브러리를 사용하여 생성된 인스턴스
  • scroll 위치

useRef() 에 넣어준 parameter 값이 .current 값의 기본 값이 된다.
수정 또는 조회시에도 .current를 이용

- App.js
import './App.css';
import React, {useRef, useState}from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';

function App() {
  const [inputs, setInputs] = useState({
    username: '',
    email: '',
  });

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

  const [users, setUsers] = useState([
    {
        id: 1,
        username: 'velopert',
        email: 'public.velopert@gmail.com'
    },
    {
        id: 2,
        username: 'tester',
        email: 'tester@gmail.com'
    },
    {
        id: 3,
        username: 'liza',
        email: 'liz@gmail.com'
    },
  ]);

  const nextId = useRef(4);
  
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers([...users, user]);

    setInputs({
      username: '',
      email: ''
    })

    nextId.current += 1;
  }

  return (
    <div className="App">
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      < UserList users = {users}/>
    </div>
  );
}

export default App;
  • CreateUser.js
import React from 'react'

function CreateUser({ username, email, onChange, onCreate }) {
    return (
        <div>
            <input
                name="username"
                placeholder='계정명'
                onChange={onChange}
                value={username}
            />
            <input
                name="email"
                placeholder='이메일'
                onChange={onChange}
                value={email}
            />
            <button onClick={onCreate}>등록</button>
            
        </div>
    );
}

export default CreateUser;
* 배열의 push, splice 등의 함수를 사용하면 안된다.
대신 spread, concat 이용 
ex : users.concat(user) 
  • onToggle, onRemove 등 함수 추가한 최종본

  • App.js

import './App.css';
import React, {useRef, useState}from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';

function App() {
  const [inputs, setInputs] = useState({
    username: '',
    email: '',
  });

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

  const [users, setUsers] = useState([
    {
        id: 1,
        username: 'velopert',
        email: 'public.velopert@gmail.com',
        active : true,      
    },
    {
        id: 2,
        username: 'tester',
        email: 'tester@gmail.com',
        active : false,
    },
    {
        id: 3,
        username: 'liza',
        email: 'liz@gmail.com',
        active : false,
    },
  ]);

  const nextId = useRef(4);

  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers([...users, user]);

    setInputs({
      username: '',
      email: ''
    })

    nextId.current += 1;
  }

  const onRemove = id => {

    setUsers(users.filter(users => users.id !== id));

  };

  const onToggle = id => {
    setUsers(
      users.map(user => user.id === id ? { ...user, active : ! user.active } : user)
    )
  }

  return (
    <div className="App">
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      < UserList users = {users} onRemove={onRemove} onToggle={onToggle}/>
    </div>
  );
}

export default App;
  • UserList.js
import React from 'react'

function User({ user, onRemove, onToggle }) {
    return (
        <div>
            <b
                style={{
                    cursor: 'pointer',
                    color: user.active? 'green' : 'black'
                }}
                onClick={()=> onToggle(user.id)}
            >
                {user.username}
            </b> 
            &nbsp;
            <span>({user.email})</span>
            <button onClick={() => onRemove(user.id)}>삭제</button>
        </div>
    )
}

function UserList({ users, onRemove, onToggle }) {
    
    return (
        <div>
            {users.map(user=> (
                <User user={user} key={user.id} onRemove={onRemove} onToggle={onToggle}/>
            ))}
        </div>
    );
}

export default UserList
profile
개발블로그

0개의 댓글