11_리액트_배열 랜더링
FrontEnd/React

11_리액트_배열 랜더링

728x90

이번에는 리액트에서 배열을 랜더링하는 방법에 대해 알아보겠다.

 

역시 UserList란 파일을 하나 만든후에 App.js에 연결해 준 후,

 

import React from 'react';


function UserList() {
    const users = [
        {
            id : 1,
            username : 'mingyu',
            email : 'mingyu@naver.com'
        },
        {
            id : 2,
            username : 'mingyu2',
            email : 'mingyu2@naver.com'
        },
        {
            id : 3,
            username : 'mingyu3',
            email : 'mingyu3@naver.com'
        }

    ];

    return (
        <div>
            <div>
                <b>{users[0].username}</b><span>({users[0].email})</span>
            </div>
            <div>
                <b>{users[1].username}</b><span>({users[1].email})</span>
            </div>
            <div>
                <b>{users[2].username}</b><span>({users[2].email})</span>
            </div>
        </div>
    );

}


export default UserList

위처럼 배열 하나를 만든다음에 단순하게 그저 username과 email이 나오도록 추출해 보았다.

 

실행화면

하지만 딱봐도 위처럼 하면 비효율적임이 느껴질 것이다.

 

 

전 글들중에서 소개했던 map 함수를 이용하면 이를 효율적으로 바꿀 수 있다.

 

//UserList.js
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 : 'mingyu',
            email : 'mingyu@naver.com'
        },
        {
            id : 2,
            username : 'mingyu2',
            email : 'mingyu2@naver.com'
        },
        {
            id : 3,
            username : 'mingyu3',
            email : 'mingyu3@naver.com'
        }

    ];

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

}


export default UserList

 

조금 헷갈릴 수 있는데 순차적으로 생각하면, map은 배열내부의 값들을 하나씩 꺼낸 후에 그 후 함수를 실행해주는 방식으로 동작된다.

 

즉 users의 배열의 인자들을 user에 넣어서 뒤 함수를 실행해보고 이를 모든 인자에 적용시키는 것이다. 

 

마치 for문에서 i를 하나씩 증가시키면서 for문 {}안의 코드를 다 실행해보는것과 같다. 

 

또한 위에서 이름이 User인 컴포넌트를 하나 만든것을 볼 수 있는데 이컴포넌트는 인자로 들어온 user의 이름과 이메일을 반환해준다. 즉, 그 인자로 users 배열의 인자를 하나씩 넣어주는 것이다.

 

이때 key를 사용하는 이유는 key가 없다면 값이 추가되거나 제거될때 매우 비효율 적이기 때문이다.

 

만약 index값을 key값으로 대체하면 첫번째 값을 제거할때 모든값을 덮어씌우는 방식으로 배열이 수정되기에 아주아주 비효율적이라고 할 수 있다.

 

 

 

useRef

 

값이 바뀌었을때 굳이 리랜더링이 필요없는 경우에 사용할 수 있다.

(ex id,setTimeout등등 굳이 리랜더링이 필요없지만 바뀌는 값을 관리하는 경우)

 

 

우선 위의 예제에서 UserList ( users) 로 바꾸어주고 배열을 App.js로 옮겼다.

 

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






function App() {

  const users = [
    {
        id : 1,
        username : 'mingyu',
        email : 'mingyu@naver.com'
    },
    {
        id : 2,
        username : 'mingyu2',
        email : 'mingyu2@naver.com'
    },
    {
        id : 3,
        username : 'mingyu3',
        email : 'mingyu3@naver.com'
    }
  
  ];

  const nextId = useRef(4);

  const onCreate = () =>{
    console.log(nextId.current); // 4
    nextId.current +=1;
  }
  
  return (
    <UserList users = {users}/>
  );
}

export default App;

즉, id가 추가되는 경우를 생각해서 위처럼 다음 Id를 설정할 수 있는 함수를 만들었을때 useRef 를 사용하면 id값이 바뀌어도 랜더링이 실행되지 않는다!

 

 

 

배열에 항목 추가하기

 

 

배열에 항목을 추가하기 위해선 어떻게 할까? 우선 아래 파일을 추가로 만들어서 이미 만들어둔 파일에 새로운 사람을 추가할 수 있는 장치를 만들어 주었다. 아래코드와 App.js를 연결하면 된다.

//CreateUser

import React from 'react';

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

export default CreateUser;

 

 

계정명,email입력이 가능해졌다.

 

 

즉 위 과정을 통해서 onClick, onChange모두 App.js에서 제어할 수 있게 되었다.

 

 

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

function App() {

  const [inputs,setInputs] = useState({ //두가지 정보를 관리하기 위해 useState사용
    username : '',
    email:'',
  });

  const { username, email } = inputs;
  const onChange = (e) =>{
    const {name,value} = e.target;
    setInputs({
      ...inputs,
      [name] : value // email이 들어오면 email이 바뀌게 된다
    });
  }

  const [users,setUsers] = useState([
    {
        id : 1,
        username : 'mingyu',
        email : 'mingyu@naver.com'
    },
    {
        id : 2,
        username : 'mingyu2',
        email : 'mingyu2@naver.com'
    },
    {
        id : 3,
        username : 'mingyu3',
        email : 'mingyu3@naver.com'
    }
  
  ]);

  const nextId = useRef(4);

  const onCreate = () =>{ //id추가작업

    const user ={
      id : nextId.current,
      username,
      email,
    };

    setUsers([...users,user]) //user의 배열을 추가 역시 복사해서 붙여넣는 방식
    setInputs ({
      username : '',
      email:''
    });
    
    
    console.log(users); // 4
    nextId.current +=1;
  }
  
  return (
    <>
      < CreateUser 
        username = { username }
        email = { email }
        onChange = { onChange}
        onCreate = { onCreate }
      />
      <UserList users = {users}/>
    </>
  );
}

export default App;

 

조금 코드가 복잡해졌는데 천천히 보면 어렵지 않다. 중요한건 배열역시 복사해서 덮어씌어주는 방식으로 항목을 추가한다는 것이다.

 

 

concat함수를 사용해서도 사용할 수 있다.

 

 setUsers(users.concat(user));

 

이 부분만 바꿔서 넣어주면 똑같이 동작함을 알 수 있다!

 

 

배열의 항목 삭제

 

배열의 항목 삭제는 추가하는것보다 단순하다.

 

//UserList.js
import React from 'react';

function User({user, onRemove}) {
    const {username,email,id} = user;

    return (
        <div>
                <b>{username}</b><span>({email})</span>
                <button onClick={() =>onRemove(id)}>삭제</button> {/* onRemove를 id를 파라미터로 실행 */}
            </div>  /*꼭 함수로 호출해줘야 전체가 사라지지 않음*/
    )
}


function UserList({users, onRemove}) {
    

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

}


export default UserList

우선 UserList컴포넌트에 onRemove를 추가해준다.  그이후, 버튼을 추가해주는데 클릭이 되었을 때 onRemove함수가 작동되게 한다. 물론 이 함수는 App.js에서 받아오게 되어 있다. 

 

 


const onRemove = id =>{
  setUsers(users.filter(user => user.id !== id));
};

  
  return (
    <>
      < CreateUser 
        username = { username }
        email = { email }
        onChange = { onChange}
        onCreate = { onCreate }
      />
      <UserList users = {users} onRemove ={onRemove}/>
    </>
  );
}

export default App;

그 이후에는 App.js밑부분에 다음과같이 onRemove함수를 추가해서 배열의 내장함수인 filter을 사용해서 제거해준다.

 

이떄 filter는 user.id가 해당 삭제버튼을 눌러서 받아온 id와 같은 부분만 삭제하게 설정되어 있다.

 

삭제가 가능하게 변경되었다.

 

배열의 항목 수정하기

 

오늘의 마지막인 배열의 항목을 수정하는 방법이다. 

 

직접 정보를 변경하진 않고, active란 bool속성인 항목을 배열에 넣어주고  그값이 false인지 true인지에 따라 글자 색이 바뀌게 하는 코드로 변경해 보겠다.

 

//UserList.js
import React from 'react';

function User({user, onRemove,onToggle}) {
    const {username,email,id, active} = user;

    return (
        <div>
                <b style ={{
                    color : active ? 'green' : 'black',
                    cursor : 'pointer'
                }}
                  onClick={() => onToggle(id)}
                >
                    {username}
                </b><span>({email})</span>
                <button onClick={() =>onRemove(id)}>삭제</button> {/* onRemove를 id를 파라미터로 실행 */}
            </div>  /*꼭 함수로 호출해줘야 전체가 사라지지 않음*/
    )
}


function UserList({users, onRemove, onToggle}) {
    

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

}


export default UserList

먼저 앞선 userlist에 onToggle함수를 추가하고, b태그에 acitve가 true이면 글자를 초록색으로 보이게 한후에 클릭되면 onToggle함수가 실행되게 설정해 두었다.

 

이때 onToggle은 active의 값을 반전시키는 역할을 하면 될 것이다.

 

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

function App() {

  const [inputs,setInputs] = useState({ //두가지 정보를 관리하기 위해 useState사용
    username : '',
    email:'',
  });

  const { username, email } = inputs;
  const onChange = (e) =>{
    const {name,value} = e.target;
    setInputs({
      ...inputs,
      [name] : value // email이 들어오면 email이 바뀌게 된다
    });
  }

  const [users,setUsers] = useState([
    {
        id : 1,
        username : 'mingyu',
        email : 'mingyu@naver.com',
        active : true  //항목 수정을 위해 추가
    },
    {
        id : 2,
        username : 'mingyu2',
        email : 'mingyu2@naver.com',
        active : false
    },
    {
        id : 3,
        username : 'mingyu3',
        email : 'mingyu3@naver.com',
        active : false
    }
  
  ]);

  const nextId = useRef(4);

  const onCreate = () =>{ //id추가작업

    const user ={
      id : nextId.current,
      username,
      email,
    };

    //setUsers([...users,user]) //user의 배열을 추가 역시 복사해서 붙여넣는 방식
    setUsers(users.concat(user));
    setInputs ({
      username : '',
      email:''
    });
    
    
    console.log(users); // 4
    nextId.current +=1;
  };


const onRemove = id =>{
  setUsers(users.filter(user => user.id !== id));
};


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


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

export default App;

위가 최종코드라서 다 올려보았다..

 

중요한건 만들어둔 배열에 active항목이 추가된 부분과, 마지막에 onToggle함수가 추가된 것만 보면 되는데,

 

삼항연산자를 통해서 id가 일치할때 즉, 내가 클릭한 버튼의 id와 배열의 id가 일치한 부분일때

다시말해서 내가 클릭한 버튼이라고 인지할대 active값을 반전시키는 것이다!

 

다음처럼 클릭하면 색이 바뀌는 것을 알 수 있다.

728x90

'FrontEnd > React' 카테고리의 다른 글

13_리액트_Context API,immer  (0) 2021.12.24
12_리액트_여러 Hook들  (0) 2021.12.23
10_리액트_input상태,useRef  (0) 2021.12.22
10_컴포넌트_JSX,props,useState  (0) 2021.12.20
09_리액트설명,작업환경 준비  (0) 2021.12.20