TC - 5번일지 (상태관리 2)

Debug-Life ·2023년 3월 9일
0

13.2. summit 버튼 구현

  1. modal 창 닫기
  2. NewPoost 컴포넌트에 입력한 본문과 저자이름 데이터를 가져와야함.
  3. 목록에 post 추가하기 (동적으로 출력되게)

✍ 1. form에 onSubmit 이벤트 추가(브라우저 기본지원)

기본적으로 form을 전송하면 Submit 이벤트가 트리거되고, 그럼 브라우저는 자동으로 HTTP 요청을 만들어 전송하는데 위에서 말한것처럼 이 동작을 안하려고함.
이 리액트 앱을 서비스하는 서버로 HTTP 요청을 보내면 페이지가 다시 로딩될 텐데 그 요청을 처리할 서버 쪽 코드가 현재는 없음. 리액트는 서버가 아니라 브라우저에서 동작하는 프런트엔드 라이브러리라서 그런 요청을 처리할 수 없음.

그래서 submit 이벤트에서 내장 메서드인 'preventDefault()' 호출 : 브라우저가 자동으로 HTTP 요청을 만들어 전송하는 걸 막음

✍ 2. 입력값 관리 코드 이전

그런데 이 작업을 하기 전에 우선 입력값을 관리해주는 PostList.jsx 에서 하위 스크립트이자 현재 작업할 NewPost.jsx 로 코드를 옮겨올 것임.

그러면 폼을 전송하더라도 전송이 안될 것이고,
이후 전송을 했으므로 업데이트가 됐을 것이므로
객체에 새롭게 업데이트된 본문과 저자이름 데이터를 담음.

그리고 폼전송을 해서 업데이트 된 객체가 담겼는지 확인을 종종해야함. console.log 를 찎어봐서 확인하기.


cf. 중간에
props.onAddPost(postData);
props.onCancel();
이 프로퍼티 둘은 함수를 값으로 받는 프로퍼티이기 때문에 호출이 가능함.

✍ NewPost.jsx

import { useState } from "react";

import classes from "./NewPost.module.css";

function NewPost(props) {
  const [enteredBody, setEnteredBody] = useState("");
  const [enteredAuthor, setEnteredAuthor] = useState("");

  function bodyChangeHandler(event) {
    setEnteredBody(event.target.value);
  }
  function authorChangeHandler(event) {
    setEnteredAuthor(event.target.value);
  }
  function submitHandler(event) {
    event.preventDefault();
    const postData = {
      body: enteredBody,
      author: enteredAuthor,
    };
    props.onAddPost(postData);
    props.onCancel();
  }

  return (
    <form className={classes.form} onSubmit={submitHandler}>
      <p>
        <label htmlFor="body">Text</label>
        <textarea id="body" required rows={3} onChange={bodyChangeHandler} />
      </p>
      <p>
        <label htmlFor="name">Your name</label>
        <input type="text" id="name" required onChange={authorChangeHandler} />
      </p>
      <p className={classes.actions}>
        <button type="button" onClick={props.onCancel}>
          Cancel
        </button>
        <button>Sumbit</button>
      </p>
    </form>
  );
}

export default NewPost;



✍ 3. useState 상태 업데이트 함수 (중요)

이전 상태를 바탕으로 새로운 상태를 만들 때는 함수 형태를 써서 상태를 업데이트 하자!

이 아래 NewPost.jsx 부분이 중요한데 setPosts 함수의 매개변수로 화살표 함수를 줬다. 그리고 existingPostsposts 는 같은 이전 상태값으로 쓰였다. 그러니까 변수명만 다를뿐, 똑같은 값이 들어있다.

리액트 훅인 useState 에서 두번쨰 인자로 들어온 함수는 상태를 업데이트 해주는 함수이고, 이 함수의 매개변수는 이전상태값이다. 즉 , posts이다.

setPosts 의 매개변수로 화살표 함수로 변경헀음.
이유 : 새로운 상태 값이 이전 상태 값을 바탕으로 한 것이기 떄문에.
왜냐하면 왜냐하면 리액트 내부에서는 상태 갱신 함수를 곧바로 실행하는 게 아니기 때문. 단지 상태 갱신을 예약해 둘 뿐.
그럼 여러 업데이트가 서로 얽혀서 일어날 때 잘못된 상태 갱신을 할 수도 있음. 그래서 리액트가 상태를 가져올떄 그 즉시 이전상태를 가져와 새 상태로 업데이트 하는것임.
이전 상태가 자동으로 들어올 테니 이를 받아 새로운 상태를 만들고 값으로 반환하면 된다.
즉, 안전하게 함수 형태로 상태를 업데이트 하자!

// 이렇게
function addPostHandler(postData) {
    setPosts((existingPosts) => [postData, ...existingPosts]);
  }

✍ NewPost.jsx

import { useState } from "react";

import Post from "./Post";
import NewPost from "./NewPost";
import Modal from "./Modal";
import classes from "./PostList.module.css";

function PostList({ isPosting, onStopPosting }) {
  const [posts, setPosts] = useState([]);

  function addPostHandler(postData) {
    setPosts((existingPosts) => [postData, ...existingPosts]);
  }

  return (
    <>
      {isPosting && (
        <Modal onClose={onStopPosting}>
          <NewPost onCancel={onStopPosting} onAddPost={addPostHandler} />
        </Modal>
      )}
      <ul className={classes.posts}>
        <Post author="Manel" body="the second props pratice!" />
      </ul>
    </>
  );
}
export default PostList;



profile
인생도 디버깅이 될까요? 그럼요 제가 하고 있는걸요

0개의 댓글