[React-The Complete Guide]Section 8: Time to Practice : A Complete Practice Project

김보나·2022년 1월 25일
0

React

목록 보기
10/15


이번 세션에서는 미니프로젝트를 진행했다.
사용자에게 이름과 나이를 입력받아 밑에 출력하는 것을 만들었고,
이용자 이름과 나이가 비어있거나 나이가 1살보다 어리면 모달로 창을 띄우는 것까지 했다.
이번 강의는 그동안 진행했던 리액트 프로젝트때 사용했던 로직과 비슷했다.
그래서 이번 포스팅은 새롭게 배운 점 및 기억해둘 것 위주로 정리했다.


children

  • 레이아웃 컴포넌트를 만들고,레이아웃을 상속받아 컴포넌트를 구성할 수 있다.
//Card.js
const Card = props => {
  return (
    <div className={`${classes.card} ${props.className}`}>{props.children}</div>
  );
};

export default Card;

//ErrorModal.js
<Card className={classes.modal}>
        <hearder>
          <h2 className={classes.header}>{props.title}</h2>
        </hearder>
        <div className={classes.content}>
          <p>{props.message}</p>
        </div>
        <footer className={classes.actions}>
          <Button onClick={props.onConfirm}>Okay</Button>
        </footer>
      </Card>

form

  • labelinputhtmlForid를 이용해서 연결해주자!
<form onSubmit={addUserHandler}>
          {/* className대신 label의 쓰임새를 정해줄때는 htmlFor사용 */}
          <label htmlFor="username">Username</label>
          <input
            id="username"
            type="text"
            value={enteredUsername}
            onChange={usernameChangeHandler}
          />
          <label htmlFor="age">Age(numbers)</label>
          <input
            id="age"
            type="number"
            value={enteredUserAge}
            onChange={ageChangeHandler}
          />
          <Button type="submit">Add User</Button>
        </form>

trim

  • 문자열의 양쪽 끝 공백을 제거함.

module.css사용하기

  1. 파일명.module.css 이름의 파일을 생성한다.
  2. module.css에서 임의로 className 을 정해서 작성한다.
  3. js파일에서 css를 임포트하고, className을 css에서 작성한 이름으로 넣어준다.

//UserList.module.css
.users {
  margin: 2rem auto;
  width: 90%;
  max-width: 40rem;
}

.users ul {
  list-style: none;
  padding: 1rem;
}

.users li {
  border: 1px solid #ccc;
  margin: 0.5rem 0;
  padding: 0.5rem;
}

//UserList.js

import React from "react";
import Card from "../UI/Card";
/* classes라는 이름으로 CSS파일을 임포트해온다. */
import classes from "./UsersList.module.css";

const UserList = props => {
  return (
/*클래스 이름을 적용해준다.*/
    <Card className={classes.users}>
      <ul>
        {props.users.map(user => (
          <li key={user.id}>
            {user.name} ({user.age} years old)
          </li>
        ))}
      </ul>
    </Card>
  );
};

export default UserList;

  1. 모달 컴포넌트를 따로 만들어준다.
    • 모달 전체를 div로 감싸준다. → 모달을 띄웠을 때 배경 역할을 함.
  2. 모달을 띄울 컴포넌트에서 모달을 트리거할 수 있는 변수를 설정하여 변수에 따라 모달 표시를 여부를 결정한다.
    • 꼭 true, false로 안해도 되고, 값이 들어있는지 안들어있는지로 해도됨!
/*error에 따라 모달창을 표시하는 컴포넌트*/
//AddUser.js
import React, { useState } from "react";
import Button from "../UI/Button";
import Card from "../UI/Card";
import ErrorModal from "../UI/ErrorModal";
import classes from "./AddUser.module.css";

const AddUser = props => {
  const [enteredUsername, setEnteredUsername] = useState("");
  const [enteredUserAge, setEnteredUserAge] = useState("");
//모달을 트리거 할 수 있는 변수
  const [error, setError] = useState();

  const addUserHandler = event => {
    event.preventDefault();
//조건에 안 맞으면 에러를 설정
    if (
      enteredUsername.trim().length === 0 ||
      enteredUserAge.trim().length === 0
    ) {
      setError({
        title: "Invaild input",
        message: "Please enter a vaild name and age (non-empty values).",
      });
      return;
    }
    if (+enteredUserAge < 1) {
      setError({
        title: "Invaild enter",
        message: "Please enter a vaild age.",
      });
      return;
    }
    props.onAddUser(enteredUsername, enteredUserAge);
    setEnteredUsername();
    setEnteredUserAge();
  };

  const usernameChangeHandler = event => {
    setEnteredUsername(event.target.value);
  };

  const ageChangeHandler = event => {
    setEnteredUserAge(event.target.value);
  };

//에러창을 끄면 error를 Null로 만들어서 에러 없애기
  const errorHandler = () => {
    setError(null);
  };

  return (
    <>
{/*error가 null이 아니라면 모달창이 뜸*/}
      {error && (
        <ErrorModal
          title={error.title}
          message={error.message}
          onConfirm={errorHandler}
        />
      )}
      <Card className={classes.input}>
        <form onSubmit={addUserHandler}>
          <label htmlFor="username">Username</label>
          <input
            id="username"
            type="text"
            value={enteredUsername}
            onChange={usernameChangeHandler}
          />
          <label htmlFor="age">Age(numbers)</label>
          <input
            id="age"
            type="number"
            value={enteredUserAge}
            onChange={ageChangeHandler}
          />
          <Button type="submit">Add User</Button>
        </form>
      </Card>
    </>
  );
};
export default AddUser;

/*에러를 표시하는 Error Modal*/

import React from "react";
import Card from "./Card";
import Button from "./Button";
import classes from "./ErrorModal.module.css";

const ErrorModal = props => {
  return (
    <>
			{/* 에러가 뜨면 모달창 뒤로 배경을 어둡게 함, 클릭시 에러가 사라짐 */}
      <div className={classes.backdrop} onClick={props.onConfirm}></div>
      <Card className={classes.modal}>
        <hearder>
          <h2 className={classes.header}>{props.title}</h2>
        </hearder>
        <div className={classes.content}>
          <p>{props.message}</p>
        </div>
				{/*okay버튼을 누르면 에러가 사라짐*/}
        <footer className={classes.actions}>
          <Button onClick={props.onConfirm}>Okay</Button>
        </footer>
      </Card>
    </>
  );
};

export default ErrorModal;

/*ErrorModal.module.css*/
.backdrop {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  z-index: 10;
  background: rgba(0, 0, 0, 0.75);
}

...

App.js에서 전역 변수 사용하기

  • Adduser컴포넌트와 UserList간에 유저들의 정보를 공유해야함.
  • 두 개의 컴포넌트의 부모 컴포넌트인 App.js에서 userList를 설정하여 props로 전달함.
    ⇒ 이런 전역변수를 관리하기 위해 context나 Redux, recoil같은 것들이 쓰인다.
import React, { useState } from "react";
import AddUser from "./components/Users/AddUser";
import UserList from "./components/Users/UsersList";

function App() {
  const [usersList, setUsersList] = useState([]);

  const addUserHandler = (uName, uAge) => {
    setUsersList(prevUserList => {
      return [
        ...prevUserList,
        { name: uName, age: uAge, id: Math.random().toString() },
      ];
    });
  };

  return (
    <div>
      <AddUser onAddUser={addUserHandler} />
      <UserList users={usersList} />
    </div>
  );
}

export default App;
  • App.js의 로직은 많으면 많을수록 성능이 떨어지니 웬만해서는 하지말자!
    ⇒ 얼른 상태관리방법을 배워야겠다.
profile
우주최강 개발자가 될 때까지😈

0개의 댓글