TIL #30 스탠다드반 5th 과제 제출

DO YEON KIM·2024년 5월 28일
0

부트캠프

목록 보기
30/72

하루 하나씩 작성하는 TIL #30


src
ㄴ App.jsx

import { useState, useEffect } from "react";
import TextInput from "./components/TextInput";
import TextList from "./components/TextList";

function App() {
  // TODO: texts 를 context api 로 리팩터링 하세요.
  const [texts, setTexts] = useState(() =>
    localStorage.getItem("texts")
      ? JSON.parse(localStorage.getItem("texts"))
      : [],
  );

  useEffect(() => {
    localStorage.setItem("texts", JSON.stringify(texts));
  }, [texts]);

  const onAddText = (text) => {
    setTexts((prevTexts) => [...prevTexts, text]);
  };

  return (
    <div>
      <h1>Text Input and Listing</h1>
      <TextInput onAddText={onAddText} />
      <TextList texts={texts} />
    </div>
  );
}

export default App;

src
ㄴcomponents
ㄴTextInput.jsx

import React, { useState } from "react";

function TextInput({ onAddText }) {
  const [inputValue, setInputValue] = useState("");

  const handleChange = (e) => {
    setInputValue(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputValue.trim()) {
      onAddText(inputValue);
      setInputValue("");
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
        placeholder="Enter text"
      />
      <button type="submit">Add</button>
    </form>
  );
}

export default TextInput;

src
ㄴcomponents
ㄴTextList.jsx

import React, { useState } from "react";

function TextInput({ onAddText }) {
  const [inputValue, setInputValue] = useState("");

  const handleChange = (e) => {
    setInputValue(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputValue.trim()) {
      onAddText(inputValue);
      setInputValue("");
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={inputValue}
        onChange={handleChange}
        placeholder="Enter text"
      />
      <button type="submit">Add</button>
    </form>
  );
}

export default TextInput;

Context API를 통해 상태를 관리하기 위하여 Context파일을 생성해준다.

src
ㄴ TextContext.jsx

// src/TextContext.jsx

import React, { createContext, useState, useEffect } from "react"; // 필요한 React 훅과 createContext 함수를 import합니다.
import PropTypes from "prop-types"; // PropTypes를 import하여 prop 타입을 검사합니다.

// Context를 생성합니다.
const TextContext = createContext();

const TextProvider = ({ children }) => { // TextProvider 컴포넌트를 정의합니다. children prop을 받습니다.
  // texts 상태를 초기화합니다. 로컬 스토리지에 저장된 값이 있으면 사용하고, 없으면 빈 배열을 사용합니다.
  const [texts, setTexts] = useState(() => 
    localStorage.getItem("texts") 
      ? JSON.parse(localStorage.getItem("texts")) 
      : []
  );

  // texts 상태가 변경될 때마다 로컬 스토리지에 저장합니다.
  useEffect(() => {
    localStorage.setItem("texts", JSON.stringify(texts));
  }, [texts]);

  // 새로운 텍스트를 추가하는 함수를 정의합니다.
  const addText = (text) => {
    setTexts((prevTexts) => [...prevTexts, text]); // 이전 texts 배열에 새로운 텍스트를 추가합니다.
  };

  return (
    <TextContext.Provider value={{ texts, addText }}> {/* TextContext.Provider를 사용해 texts와 addText 함수를 제공합니다. */}
      {children} {/* Provider 내부의 children을 렌더링합니다. */}
    </TextContext.Provider>
  );
};

// children prop의 타입을 검사합니다.
TextProvider.propTypes = {
  children: PropTypes.node.isRequired,
};

// TextContext와 TextProvider를 export합니다.
export { TextContext, TextProvider };

main.jsx파일에서 Textprovider를 사용하여 애플리케이션 감싸기

src
ㄴmain.jsx

// src/main.jsx

import React from "react"; // React를 import합니다.
import { createRoot } from "react-dom/client"; // createRoot를 import합니다.
import App from "./App.jsx"; // App 컴포넌트를 import합니다.
import { TextProvider } from "./TextContext.jsx"; // TextProvider를 import합니다.

const container = document.getElementById("root"); // root DOM 엘리먼트를 가져옵니다.
const root = createRoot(container); // createRoot를 사용해 root를 생성합니다.

root.render(
  <TextProvider> {/* TextProvider로 App을 감쌉니다. */}
    <App /> {/* App 컴포넌트를 렌더링합니다. */}
  </TextProvider>
);

Context 사용하기 - TextInput.jsx와 TextList.jsx 컴포넌트에서 TextContext를 사용하여 상태에 접근하고 업데이트

src
ㄴcomponents
ㄴTextInpt.jsx

// src/components/TextInput.jsx

import React, { useState, useContext } from "react"; // React, useState, useContext를 import합니다.
import { TextContext } from "../TextContext.jsx"; // TextContext를 import합니다.

function TextInput() { // TextInput 컴포넌트를 정의합니다.
  const [inputValue, setInputValue] = useState(""); // inputValue 상태를 초기화합니다.
  const { addText } = useContext(TextContext); // TextContext에서 addText 함수를 가져옵니다.

  const handleChange = (e) => { // 입력 값이 변경될 때 호출되는 함수입니다.
    setInputValue(e.target.value); // inputValue 상태를 업데이트합니다.
  };

  const handleSubmit = (e) => { // 폼이 제출될 때 호출되는 함수입니다.
    e.preventDefault(); // 폼의 기본 제출 동작을 막습니다.
    if (inputValue.trim()) { // 입력 값이 비어 있지 않은 경우에만
      addText(inputValue); // addText 함수를 호출하여 새로운 텍스트를 추가합니다.
      setInputValue(""); // 입력 필드를 비웁니다.
    }
  };

  return (
    <form onSubmit={handleSubmit}> {/* 폼 제출 이벤트 핸들러를 설정합니다. */}
      <input
        type="text"
        value={inputValue} {/* inputValue 상태를 input의 값으로 설정합니다. */}
        onChange={handleChange} {/* 입력 값이 변경될 때 handleChange 함수를 호출합니다. */}
        placeholder="Enter text" {/* 입력 필드에 플레이스홀더를 설정합니다. */}
      />
      <button type="submit">Add</button> {/* 제출 버튼을 렌더링합니다. */}
    </form>
  );
}

export default TextInput; // TextInput 컴포넌트를 export합니다.

src
ㄴcomponents
ㄴTextList.jsx

// src/components/TextList.jsx

import React, { useContext } from "react"; // React와 useContext를 import합니다.
import { TextContext } from "../TextContext.jsx"; // TextContext를 import합니다.

function TextList() { // TextList 컴포넌트를 정의합니다.
  const { texts } = useContext(TextContext); // TextContext에서 texts 배열을 가져옵니다.

  return (
    <ul>
      {texts.map((text, index) => ( // texts 배열을 순회하며 각 텍스트를 li 요소로 렌더링합니다.
        <li key={index}>{text}</li> // key로 인덱스를 사용하여 고유성을 보장합니다.
      ))}
    </ul>
  );
}

export default TextList; // TextList 컴포넌트를 export합니다.
profile
프론트엔드 개발자를 향해서

0개의 댓글