외거노비
외거노비 일지
외거노비

공지사항

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 분류 전체보기 (35)
    • 스파르타 프로젝트 (1)
      • 소개페이지(feat. 팀 외거노비) (1)
      • 프로젝트(미정)(feat. 팀 외래교란종) (0)
    • 스파르타 개발일지 (34)
hELLO · Designed By 정상우.
외거노비

외거노비 일지

개발일지 20221208 리액트 입문 3 실습
스파르타 개발일지

개발일지 20221208 리액트 입문 3 실습

2022. 12. 8. 21:27

실습)

1. Counter 만들기

+버튼과 -버튼을 누를 때 숫자가 카운트된다

import React, { useState } from "react";

function App() {
  const [number, setNumber] = useState(0);
  return (
    <div>
      {number}
      <button onClick={() => {setNumber(number + 1);}}> + </button>
      <button onClick={() => {setNumber(number - 1);}}> - </button>
    </div>
  );
}

export default App;

 

2. js css파일 분리하기

 

예제 1)

import React from "react";
import "./App.css";

const App = () => {
  const style = {
    padding: "100px",
    display: "flex",
    gap: "12px",
  };
  const squareStyle = {
    width: "100px",
    height: "100px",
    border: "1px solid green", // 1px의 초록색 실선 테두리
    borderRadius: "10px",
    display: "flex",
    alignItems: "center", // 중앙정렬
    justifyContent: "center", // 행의 위치
  };
  return (
    <div style={style}>
      <div style={squareStyle}>감자</div>
      <div style={squareStyle}>고구마</div>
      <div style={squareStyle}>오이</div>
      <div style={squareStyle}>가지</div>
      <div style={squareStyle}>옥수수</div>
    </div>
  );
};

export default App;

=> css파일과 js파일 분리하면

// App.css
.app-style {
  padding: 100px;
  display: flex;
  gap: 12px;
}

.square-style {
  width: 100px;
  height: 100px;
  border: 1px solid green;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}
// App.js
import React from "react";
import "./App.css";

const App = () => {
  return (
    <div className="app-style">
      <div className="square-style">감자</div>
      <div className="square-style">고구마</div>
      <div className="square-style">오이</div>
      <div className="square-style">가지</div>
      <div className="square-style">옥수수</div>
    </div>
  );
};

export default App;

* jsx문법을 사용하기 때문에 js파일은 웬만하면 jsx로 수정하기!! ex) App.js -> App.jsx

 

같은 코드의 중복을 막기 위해 map과 filter 적용↓

import React from "react";
import "./App.css";

const App = () => {
  const vegetables = ["감자", "고구마", "오이", "가지", "옥수수"];
  return (
    <div className="app-style">
      {/* jsx 부분에서 js코드(map)을 작성할 것이기 때문에 {}를 사용 */}
      {vegetables.map((vegetableName) => {
        return (
          <div className="square-style" key={vegetableName}>
            {vegetableName}
          </div>
        );
      })}
    </div>
  );
};

export default App;

 

예제 2)

import React from "react";
import "./App.css"; // 🔥 반드시 App.css 파일을 import 해줘야

function User(props) {
  return (
    <div className="square-style">
      {props.user.age}살 - {props.user.name}
    </div>
  );
}
const App = () => {
  const users = [
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" },
  ];
  return (
    <div className="app-style">
      {users.map((user) => {
        return <User user={user} key={user.id}></User>;
      })}
      {/* 각각의 user에 대한 props를 넘겨줌 */}
    </div>
  );
};

export default App;

 

 

실습 - 삭제&취소 버튼)

import React, { useState } from "react";
import "./App.css"; // 🔥 반드시 App.css 파일을 import 해줘야

function CustomButton(props) {
  const { color, onClick, children } = props;
  if (color) {
    return (
      <button
        style={{ backgroundColor: color, color: "white" }}
        onClick={onClick}
      >
        {children}
      </button>
    );
  }
  // 만약 받아온 props에 color가 있다면 컬러버튼을 return할 것!
  return <button onClick={onClick}>{children}</button>;
}

function User(props) {
  return (
    <div className="square-style">
      {props.user.age}살 - {props.user.name}
      <CustomButton
        color="red"
        onClick={() => props.handleDelete(props.user.id)}
      >
        삭제하기
      </CustomButton>
    </div>
  );
}

const App = () => {
  const [users, setUsers] = useState([
    // 추가 및 삭제를 하기 위해 useState사용
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" },
  ]);
  const [name, setName] = useState("");
  const [age, setAge] = useState("");

  const addUserHandler = () => {
    const newUser = { id: users.length + 1, age: age, name: name };
    //user(배열)의 길이를 추가한다는 뜻!
    setUsers([...users, newUser]); // 기존 users 배열에 추가해주는 코드
    // 배열을 만들고, 스프레드문법을 통해 기존에 있던 users 배열에 추가한다는 의미
  };
  const deleteUserHandler = (id) => {
    // 삭제버튼 // 삭제할 id 받기
    const newUserList = users.filter((user) => user.id !== id);
    // user의 id가 설정한 id와 같지 않으면, 그것만 filter해서 새로운 유저리스트를 만듦
    setUsers(newUserList);
    // const newUserList = ;
    // setUsers(users.filter((user) => user.id !== id));
    // 일회성 변수가 싫다면 위의 두 줄을 사용해도 괜찮음
  };

  return (
    <div>
      <div className="app-style">
        {users.map((user) => {
          return (
            <User
              handleDelete={deleteUserHandler}
              user={user}
              key={user.id}
              // 리액트에서 컴포넌트 배열을 렌더링할 때,
              // 각각의 원소에서 변동이 있는지 알아내려고 사용하는 것이기 때문에 key값이 필요
              // 만약 key가 없다면 리액트는 가상DOM을 비교하는 과정에서 배열을 순차적으로
              // 비교하면서 변화를 감지하려고 할 것
              // key로 어떤 변화가 일어났는지 더 빠르게 알아낼 수 있음!(리액트 성능 최적화)
              // props처럼 생겼지만 props로 설정하지 않아도 key는 넣을 수 있음
            ></User>
          );
        })}
        {/* handleDelete={deleteUserHandler} -> user에 Props로 delete 함수를 넣음*/}
        {/* 각각의 user에 대한 props를 넘겨줌 */}
      </div>
      <input
        value={name}
        placeholder="이름을 입력해주세요"
        // 인풋 이벤트로 들어온 입력 값을 name의 값으로 업데이트
        onChange={(e) => setName(e.target.value)}
      />
      <input
        value={age}
        placeholder="나이를 입력해주세요"
        // 인풋 이벤트로 들어온 입력 값을 age의 값으로 업데이트
        onChange={(e) => setAge(e.target.value)}
      />
      <CustomButton color="green" onClick={addUserHandler}>
        추가하기
      </CustomButton>
    </div>
  );
};

export default App;

위의 예제에서 age가 25 이상인 user를 제외하고 렌더링↓

import React, { useState } from "react";
import "./App.css"; // 🔥 반드시 App.css 파일을 import 해줘야

function CustomButton(props) {
  const { color, onClick, children } = props;
  if (color) {
    return (
      <button
        style={{ backgroundColor: color, color: "white" }}
        onClick={onClick}
      >
        {children}
      </button>
    );
  }
  return <button onClick={onClick}>{children}</button>;
}

function User(props) {
  return (
    <div className="square-style">
      {props.user.age}살 - {props.user.name}
      <CustomButton
        color="red"
        onClick={() => props.handleDelete(props.user.id)}
      >
        삭제하기
      </CustomButton>
    </div>
  );
}

const App = () => {
  const [users, setUsers] = useState([
    // 추가 및 삭제를 하기 위해 useState사용
    { id: 1, age: 30, name: "송중기" },
    { id: 2, age: 24, name: "송강" },
    { id: 3, age: 21, name: "김유정" },
    { id: 4, age: 29, name: "구교환" },
  ]);
  const [name, setName] = useState("");
  const [age, setAge] = useState("");

  const addUserHandler = () => {
    const newUser = { id: users.length + 1, age: age, name: name };
    setUsers([...users, newUser]);
  };
  const deleteUserHandler = (id) => {
    const newUserList = users.filter((user) => user.id !== id);
    setUsers(newUserList);
    // const newUserList = ;
    // setUsers(users.filter((user) => user.id !== id)); 로 사용해도 괜찮음
  };

  return (
    <div>
      <div className="app-style">
        {users.map((user) => {
          if (user.age < 25) {
            return (
              <User
                handleDelete={deleteUserHandler}
                user={user}
                key={user.id}
              ></User>
            );
          } else {
            return null; // 25세 이상은 출력하지 않음
          }
        })}
        {/* handleDelete={deleteUserHandler} -> user에 Props로 delete 함수를 넣음*/}
        {/* 각각의 user에 대한 props를 넘겨줌 */}
      </div>
      <input
        value={name}
        placeholder="이름을 입력해주세요"
        // 인풋 이벤트로 들어온 입력 값을 name의 값으로 업데이트
        onChange={(e) => setName(e.target.value)}
      />
      <input
        value={age}
        placeholder="나이를 입력해주세요"
        // 인풋 이벤트로 들어온 입력 값을 age의 값으로 업데이트
        onChange={(e) => setAge(e.target.value)}
      />
      <CustomButton color="green" onClick={addUserHandler}>
        추가하기
      </CustomButton>
    </div>
  );
};

export default App;

 

Component 분리하기)

 

협업하는 다른 개발자가 js파일을 보고 어떤 Component가 있을지 유추하기는 쉽지 않음

그래서, 일반적으로 계속 렌더링 해서 기능을 재사용하는 Component를 따로 분리해서 사용함!

 

+) 추후 정리해서 추가할 예정

 

 

 

후기)

과제로 todo-list 만들기가 있는데 벌써 큰일이다ㅠㅋㅋㅋㅋ

리액트 입문강의 개인과제가 벌써부터 이렇게 어렵게 느껴지는데 숙련강의 심화강의를 내가 잘 이해할 수 있을까

State Props를 알면 리액트를 얼추 알게 된 거라고 할 수 있댔는데, 개념은 이해가 되는데 코드에 적용하는 데서 막힌다

숙련강의 듣기 전에 todo-list 만들기 과제를 스스로의 힘으로 완성하고 싶지만 쉽지 않다ㅎㅎㅠㅠ

 

'스파르타 개발일지' 카테고리의 다른 글

개발일지 20221212 리액트 숙련 강의 1  (0) 2022.12.12
개발일지 20221210~11 todo-list 만들기  (0) 2022.12.11
개발일지 20221207 리액트 입문 2  (0) 2022.12.07
개발일지 20221206 리액트 입문 강의 시작!  (0) 2022.12.06
개발일지 20221122 SPA, Firebase Setup 특강 정리 + 두 번째 프로젝트  (0) 2022.11.22
    '스파르타 개발일지' 카테고리의 다른 글
    • 개발일지 20221212 리액트 숙련 강의 1
    • 개발일지 20221210~11 todo-list 만들기
    • 개발일지 20221207 리액트 입문 2
    • 개발일지 20221206 리액트 입문 강의 시작!

    티스토리툴바