상세 컨텐츠

본문 제목

[React] List 에 새로운 object인 항목 추가하기 w/ useState, onClick and inputs

Study with me

by Agathe_1024 2022. 12. 29. 19:09

본문

이번에는 새로운 object data를 추가해 list 화면에 보여주고자 합니다.

 

주의할 점은

1. input 하나만이 아니라, 여러 input이 들어간 object 형식

2. 지난번과 마찬가지로 추가하는 정보를 담은 양식을 컴포넌트화할 것이기 때문에 props 전달

3. 그리고 저장 버튼을 눌렀을 때 list 화면에 보여줌

4. 이 때에 기존 array에 push하는 것이 아니라, useState를 통해 기존 data array를 유지

입니다.

 

일단 컴포넌트부터 제작 ㄱㄱ

const NewPostForm = () => {
  return (
    <WrapForm>
      <Title>새 맛집 추가하기</Title>
      <WrapInputs>
        <Input
          name="location"
          placeholder="지역명"
          value={location}
        />
        <Input
          name="title"
          placeholder="상호명"
          value={title}
        />
        <Input
          name="sort"
          placeholder="종류"
          value={sort}
        />
        <Input
          name="address"
          placeholder="주소"
          value={address}
        />
        <Input
          name="call"
          placeholder="전화번호"
          value={call}
        />
        <Input
          name="visitedAt"
          placeholder="방문일"
          value={visitedAt}
        />
      </WrapInputs>
      <BtnSave>저장</BtnSave>
    </WrapForm>
  );
};

아참 css는 emotion을 사용하고 있습니다. 적당히 맘대로 이쁘게 만듭시다.

input에 있는 name과 value는 원래 array mock data(posts라는 상수에 있습니다)에 있는

location, title, sort, address, call, visitedAt과 동일하게 합니다.

 

이제 App.js로 돌아가 새로운 데이터를 상태관리 할 useState를 설정합니다.

각 key와 value가 있는 객체가 초기값이 됩니다.

  const [newPostInputs, setNewPostInputs] = useState({
    location: "",
    title: "",
    sort: "",
    address: "",
    call: "",
    visitedAt: "",
  });

그리고 newPostInputs에 담기는 정보들인 location, title, sort, address, call, visitedAt을 쏙 뽑아줍니다.

이는  state값을 각각 변수에 담기 위해서입니다.

 const { location, title, sort, address, call, visitedAt } = newPostInputs;

 

 

얘네들이 곧 자식 컴포넌트(새로운 정보들을 입력할 form)로 보내질 props가 됩니다.

이제 앞서 만들었던 NewPostForm 컴포넌트에 props로 넣어줍시다.

const NewPostForm = ({
  location,
  title,
  sort,
  address,
  call,
  visitedAt,
}) => {
  return (
    <WrapForm>
      <Title>새 맛집 추가하기</Title>
      <WrapInputs>
        <Input
          name="location"
          placeholder="지역명"
          value={location}
        />
        ...
   )
   export default NewPostForm;

 

다시 App.js로 돌아가, input 안에 정보를 작성하거나 입력하는 이벤트가 발생하고,

그 변화에 맞춰 실행해주는 함수를 작성합니다.

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

여기서 { name, value }는 input에 들어가는 속성인 name과 value입니다.

event 가 실행되는 target html이 곧 각 name의 value로 할당되어질 것입니다.

 

그리고 setNewPostInputs를 실행합니다.

당초 const [newPostInputs, setNewPostInputs] = useState({...}) 객체였으므로

여기서 setNewPostInputs 또한 객체로 표현해줘야합니다.

spread operator를 통해 바뀌는 것을 제외한 나머지 정보들을 그대로 가져오고(...newPostInptus),

함수 내부에서 외부의 변수를 속성명으로 사용할 때에는 [] 를 사용하여,

newPostInputs의 상태를 업데이트하도록 합니다.

 

완성된 onChange함수를 NewPostForm 에 넣어줍니다.

const NewPostForm = ({
  location,
  title,
  sort,
  address,
  call,
  visitedAt,
  onChange,
}) => {
  return (
    <WrapForm>
      <Title>새 맛집 추가하기</Title>
      <WrapInputs>
        <Input
          name="location"
          placeholder="지역명"
          value={location}
          onChange={onChange}
        />
   ...
   )
   export default NewPostForm;

 

마지막으로 저장 버튼을 눌렀을 때 input에 작성한 정보들이 list 화면에 뜨도록 합니다.

 

우선, id를 input에 작성할 때 굳이 적어주지 않고, 자동으로 1씩 증가하도록 만들고싶습니다.

 const nextId = useRef(5);

useRef() 를 사용합니다.

초기값이 5인 이유는 mock data 에 id가 1부터 시작하는 4개의 객체를 이미 넣어두었기 때문입니다.

  const onCreate = () => {
    const newPost = {
      id: nextId.current,
      location,
      title,
      sort,
      address,
      call,
      visitedAt,
    };
    setContents([...contents, newPost]);
    setNewPostInputs({
      location: "",
      title: "",
      sort: "",
      address: "",
      call: "",
      visitedAt: "",
    });
    nextId.current += 1;
  };

onCreate 함수 내 새로운 정보가 담기는 newPost 를 설정합니다.

이 newPost는 setContents를 통해 기존 contents들에 추가로 더해지도록 만듭니다.

 

id는 위에 useRef()로 만들어둔 5를 받도록 합니다.

 

setContents는 원래 mock data에 직접 새로운 정보를 주입해 주는 게 아니라(push함수같은 거),

예전 array와 비교하여 새로운 data를(newPost) 덧붙여줍니다.

(새로고침하면 입력한 데이터는 사라질거예요)

 

setNewPostInputs 함수를 다시 실행합니다.

저장 버튼을 누르면 이 컴포넌트의 input들은 다시 빈값으로 돌아갑니다.

 

마지막으로 다음에 저장버튼을 누를 때는 id가 현재값(5)에서 1이 증가되도록 합니다.

 

완성한 onCreate 함수도 NewPostForm 컴포넌트에 props로 보내줍니다.

const NewPostForm = ({
  location,
  title,
  sort,
  address,
  call,
  visitedAt,
  onChange,
  onCreate,
}) => {
  return (
    <WrapForm>
      <Title>새 맛집 추가하기</Title>
      <WrapInputs>
        <Input
          name="location"
          placeholder="지역명"
          value={location}
          onChange={onChange}
        />
  ...
  
        <BtnSave onClick={onCreate}>저장</BtnSave>
     </WrapForm>
  );
};

 

결과물

 

ui가 썩 깔끔한 상태가 아니지만 일단 넘어가는걸로..ㅋㅋ

맛집 추가 양식에 정보를 입력하고 저장 버튼을 누르면

list 화면에 잘 뜬다.

새로 뜬 list item을 클릭하면 modal창이 뜨고,

modal창이 뜨면 그 정보를 console.log로 살펴보았을 때 id도 각가 5, 6으로 제대로 뜬다.

 

추가로 공부해야 할 것 : 비구조화 할당

 

그나저나 양포항과 정든면 둘 다 맛집이니 남천동 오시면 한 번 드셔보세요ㅋㅋㅋㅋㅋ

 

참고한 글

https://cocoon1787.tistory.com/790

 

[React] 리액트 배열 항목 추가, 제거, 수정

작업환경 $ npm install -g create-react-app $ create-react-app 프로젝트파일명 해당 포스팅은 VScode에서 create-react-app을 통해 만들어진 React 파일에서 작업한 내용입니다. 배열에 항목 추가하기 상태 관리 및

cocoon1787.tistory.com

https://ossam5.tistory.com/166

 

[React강좌] 14강 배열에 데이터 추가하기 - 오쌤의 니가스터디

1. useRef로 컴포넌트 안의 변수 만들기 - ref의 원래 기능은 컴포넌트에서 특정 DOM을 선택해야할 때, ref 혹은 useRef()함수를 사용해야한다고 배웠습니다. ossam5.tistory.com/164?category=921604 [React] 12강 ref

ossam5.tistory.com

 

남천동 맛집

양포항(부산 수영구 남천동로9번길 55 1층)

아구불고기가 맛있는 집!

점심시간대에 아구덮밥 강추합니다!

https://www.instagram.com/yangpohang_ulsan/

정든면(부산광역시 수영구 광남로22번길 17, 1층 (남천동))

자가제면 고기국수가 맛있는 집!

야들야들한 면과 베지근한 국물맛이 일품이예요!

https://www.instagram.com/jeong__dm/

관련글 더보기