React + Vite | 코드 정리 및 복습하기

하영·2024년 7월 13일
0

React

목록 보기
18/19

두둥 너무 어렵습니다.
CRA를 먼저 완강을 하고 vite를 사용한 강의를 듣는게 맞았을까 싶기도 하구욤...
아직 useEffect나 라우트 등등 배울게 천리만리인데 지금까지 공부하고 작성한 코드도 겨우겨우 이해가 되는 중이다.
본캠프에서 리액트 배우고 vite 쓴다고 했으니까 급하게 완강하지 말고 공부할 수 있는 만큼, 제대로 코드를 아는게 좋을 것 같았다.
그래서 지금까지 작성한 jsx 파일을 정리한다 생각하고 복습하려한다..!

리액트 코드 정리


1) App.jsx

import { useState } from "react";

import PostsList from "./components/PostsList";
import MainHeader from "./components/MainHeader";

function App() {
  const [modalIsVisible, setModalIsVisible] = useState(false); // false: 첫 화면에서 모달 안 보이게함

  function showModalhandler() { //모달창 뜨게 하는 함수
    setModalIsVisible(true);
  }

  function hideModalHandler() { //모달창 숨기는 함수
    setModalIsVisible(false);
  }
  return (
    <>
      <MainHeader onCreatePost={showModalhandler} />
      <main>
        <PostsList isPosting={modalIsVisible} onStopPosting={hideModalHandler} />
      </main>
    </>
  );
}
  • MainHeader 를 클릭하면 showModalhandler에 의해 모달창이 열린다.
  • PostsList 컴포넌트에서 isPosting 상태면 모달창이 보이고, onStopPosting 이면 모달창이 숨겨진다.

2) Post.jsx

import classes from './Post.module.css';

function Post(props) {
    return (
        <li className={classes.post}>
            <p className={classes.author}>{props.author}</p>
            <p className={classes.text}>{props.body}</p>
        </li>
    );
}

export default Post;
  • Post(props) = Post{author, body} 로 변경 가능
  • 객체로 접근해서 값들을 넘겨받아 출력한다.

3) PostsList.jsx

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

    function addPostHandler(postData) {//새로운 글 추가 함수
        setPosts((existingPosts) => [postData, ...existingPosts]);
    }
    return (
        <>
            {isPosting ? (
                <Modal onClose={onStopPosting}>
                    <NewPost
                        onCancel={onStopPosting} onAddPost={addPostHandler}
                    />
                </Modal>
            ) : false}
            {posts.length > 0 && (
                <ul className={classes.posts}>
                    {posts.map((post) => <Post key={post.body} author={post.author} body={post.body} />)}
                </ul>
            )}
            {posts.length === 0 && <div style={{ textAlign: 'center', color: 'white' }}>
                <h2>There are no posts yet.</h2>
                <p>Start adding some!</p>
            </div>}
        </>
    );
}

export default PostsList;
  • author, body 값을 각각 객체로 담아둔 postData를 가져와서 사용
  • setPosts는 이전에 작성된 포스트를 바탕으로 새로운 포스트가 추가되는 것
    ⭐️ 상태를 업데이트할 때 새로운 상태 값이 이전 상태 값을 바탕으로 한 것이라면
    setPosts(새로 추가되는 내용)에 함수(화살표 함수같은 것)를 넘겨주어야한다.
    이 함수는 자동으로 호출되는데 기본적으로 현재 상태(-> existingPosts)의 스냅샷을 받고, 그 다음 새로운 상태 값을 반환해야한다.
  • isPosting === true 이면 Modal컴포넌트가 보여지고 NewPost 컴포넌트에 의해 글을 쓸 수 있다.
    NewPost에는 버튼이 2개 있는데 하나는 취소(모달창 닫힘), 다른 하나는 추가(submit)되는 버튼이다.
    false 대신에 null 써도 됨 >> 모달창 사라짐
    ⭐️ Post key={post.body} 처럼 key 값을 적어주어야 원하는대로 값을 불러와서 보여질 수 있다.
  • posts의 개수가 1개 이상이면 post 객체값을 불러와서 보여준다
    posts의 개수가 0, 즉 없으면 div 안 문장 보여진다.

4) NewPost.jsx

import classes from './NewPost.module.css';
import { useState } from 'react';

function NewPost({ onCancel, onAddPost }) {
  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
    };
    onAddPost(postData); // 데이터를 받아서 포스트 추가
    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={onCancel}>Cancel</button>
        <button>Submit</button>
      </p>
    </form>
  );
}

export default NewPost;
  • submitHandler 함수를 추가하면서 submit 버튼의 기본 속성을 막기 위해 event.preventDefault(); 작성
  • postData 안에 내용과 작성자 값을 객체로 담아주었다.
  • postData 의 값을 받아와서 화면에 추가 onAddPost(postData)하는 함수를 실행하고 그 다음 모달창을 닫기 위해 onCancel() 함수를 작성한다.
    ⭐️ 객체로 담은 postData를 매개변수로 사용했기 때문에 위 3) PostsList.jsx 에서 사용할 수 있게 된다.

5) Modal.jsx

import classes from './Modal.module.css';

function Modal({ children, onClose }) {
    return (
        <>
            <div className={classes.backdrop} onClick={onClose} />
            <dialog open className={classes.modal}>{children}

            </dialog>
        </>
    )
}

export default Modal;
  • 객체 구조 분해(children)는 다른 프로퍼티에도 사용 가능하다.
    그동안 Post author, body로 내가 직접 속성과 이름을 만들어서 사용했지만 children은 다르다.
    children이 참조하는 건 언제나 사용자정의 컴포넌트의 본문태그 안에 담겨 사용되는 콘텐츠이다. (예약된 속성임)

이 children은 위에 코드들과 연결해서 설명이 필요하다.

잠시 PostsList컴포넌트를 보면 Modal 컴포넌트를 만들어서 import하고 NewPostModal태그로 래핑해준다.

백드롭 css로 살짝 회색빛은 보이는 효과는 성공했지만, "폼과 모달은 보이지 않는 문제가 발생한다"

그 이유는 어떤 콘텐츠(컴포넌트 or 다른 기본 내장 요소 등등) 를 다른 사용자 정의 컴포넌트(여기서는 Modal)로 래핑하면,
리액트는 컴포넌트의 어느 위치에 래핑된 콘텐츠를 표시해야 할지 알 수 없다.
(Modal 컴포넌트 어디에 해야할지 모른다는 뜻)

따라서 리액트에게 어디에 표시해야할지 알려줘야 하는데 이때 children을 사용하면 된다.
작성법은 props.children 으로 쓰거나 객체구조분해를 통해 {children} 으로 적을 수 있다.



이해한 선에서 복습하면서 정리한거라서 설명에 틀린 부분이 가득할 수 있슴다..
리액트를 조금 더 사용해보고 기초단계를 넘어서면 강의 코드를 다시 리뷰해야겠다.


출처

  • 유데미 리액트 강의 " Next.js 14 & React - 완벽 가이드"
profile
왕쪼랩 탈출 목표자의 코딩 공부기록

0개의 댓글