프론트엔드/React

리액트의 배열

alswlfl 2022. 11. 17. 15:15

배열에 항목 추가

: 배열에 변화를 줄 때, 객체와 마찬가지로 불변성을 지켜주어야 함

➣ 기존의 배열을 한 번 복사하고 나서 사용

 

App컴포넌트에서 상태관리하고, CreateUser컴포넌트에서는 input값 및 이벤트로 등록할 함수들을 props로 넘겨받아 사용하는 예제

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;

1. spread 연산자 사용

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@example.com",
    },
    {
      id: 3,
      username: "liz",
      email: "liz@example.com",
    },
  ]);

  const nextId = useRef(4); //useRef() 사용할 때 파라미터 넣어주면, 이 값이 .current값의 기본값이 됨
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email,
    };
    setUsers([...users, user]);  //spread 사용
    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
  };
  return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} />
    </>
  );
}

export default App;

2. concat함수 사용

concat함수: 기존의 배열을 수정하지 않고, 새로운 원소가 추가된 새로운 배열을 만들어줌

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@example.com",
    },
    {
      id: 3,
      username: "liz",
      email: "liz@example.com",
    },
  ]);

  const nextId = useRef(4); //useRef() 사용할 때 파라미터 넣어주면, 이 값이 .current값의 기본값이 됨
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email,
    };
    setUsers(users.concat(user));  //concat함수 이용
    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
  };
  return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} />
    </>
  );
}

export default App;

 

배열에 항목 제거

import React from "react";

function User({ user, onRemove }) {
	//삭제 버튼이 클릭될 때 user.id값을 props로 받아올 onRemove함수의 파라미터로 넣어 호출
   	//onRemove는 id가 _인 객체 삭제
  return (
    <div>
      <b>{user.username}</b> <span>({user.email})</span>
      <button onClick={() => onRemove(user.id)}>삭제</button> 
    </div>
  );
}

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

export default UserList;
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@example.com",
    },
    {
      id: 3,
      username: "liz",
      email: "liz@example.com",
    },
  ]);

  const nextId = useRef(4); //useRef() 사용할 때 파라미터 넣어주면, 이 값이 .current값의 기본값이 됨
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email,
    };
    setUsers(users.concat(user));
    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
  };

  const onRemove = (id) => {
    //user.id가 파라미터로 일치하지 않는 원소만 추출하여 새로운 배열을 만듦
    //=user.id가 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;

- 불변성을 지키면서 특정 원소를 배열에서 제거하기 위해 filter 배열 내장 함수 사용

- filter 함수는 배열에서 특정 조건이 만족하는 원소들만 추출하여 새로운 배열 만들어줌

 

배열 항목 수정

import React from "react";

function User({ user, onRemove, onToggle }) {
//cursor: 마우스 올렸을 때 커서의 모양 변경
  return (
    <div>
      <b
        style={{ cursor: "pointer", color: user.active ? "green" : "black" }}
        onClick={() => onToggle(user.id)}
      >
        {user.username}
      </b>
      <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;
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@example.com",
      active: false,
    },
    {
      id: 3,
      username: "liz",
      email: "liz@example.com",
      active: false,
    },
  ]);

  const nextId = useRef(4); //useRef() 사용할 때 파라미터 넣어주면, 이 값이 .current값의 기본값이 됨
  const onCreate = () => {
    const user = {
      id: nextId.current,
      username,
      email,
    };
    setUsers(users.concat(user));
    setInputs({
      username: "",
      email: "",
    });
    nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
  };

  const onRemove = (id) => {
    //user.id가 파라미터로 일치하지 않는 원소만 추출하여 새로운 배열을 만듦
    //=user.id가 id인 것을 제거
    setUsers(users.filter((user) => user.id !== id));
  };
  
  const onToggle = (id) => {
    setUsers(
      users.map((user) =>  // 배열의 불변성을 유지하며 배열 업데이트하기 위해 map함수 사용
        user.id === id ? { ...user, active: !user.active } : user  //id값 비교하여 같으면 active 값 반전, 아닐 경우 그대로 두기
      )
    );
  };
  return (
    <>
      <CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      />
      <UserList users={users} onRemove={onRemove} onToggle={onToggle} />
    </>
  );
}

export default App;