본문 바로가기
프론트엔드로 가는 길/코딩기능구현스터디

1주차 과제 - 총정리

by woody-j 2023. 1. 29.
소요시간 : 23.01.10 ~ 23.01.28

생각 : 너무나도 게으른 탓에 너무 오랜 시간을 잡아먹었다. 그리고 성공하지 못한 기능도 있었다.
하나가 막히면 그 하나를 물고 늘어지는 바람에 더 오래 걸린 것도 있었다. 
그 막힌 문제만 풀면 변기 뚫리듯 술술 풀리는데 말이다.
막힌다고해서 좌절했더니... 더 오래 걸렸던 것 같다. 
지금은 올바른 코드도 아니고 깔끔하게 작성도 하지 않았다.
내 능력으로는... 이게 한계일까 생각이 들면서도 조금씩 올바르고 깔끔해지는 코드를 발견할 수 있을 거라 생각이 든다.
왜냐면 난 멋지고 대단하니까...

매일 공부를 하면서 느낀 것은 내가 집중력도 너무 없고, 의지가 박약이라는 것.
끈기가 없다보니 하다가 말고 하다가 말고 그래서 코드 작성하는데 뭐했더라 뭐해야하지를 반복했던 것 같다.
이제는 막히더라도 하나는 깔끔하게 끝내도록 해보자.
그리고 코드를 예쁘게 쓰는 방법은 어디든지 나와있으니까 조금은 참고해보자.

그리고 이번 과제의 제일 큰 문제는 '구조'라고 생각이 들었다.
시작부터 구조와 과정을 확실하게 짚고 넘어가야 나중에 산으로 안간다는 것을 깨달았다.
내가 등산을 좋아해서.. 계속 코드가 산으로 가는 걸까....?
다음 과제는 꼭 이세돌마냥 앞을 내다보고 코드를 짜야겠다.

기능 구현 할때 마다 블로그 정리 하도록!

https://juhee067.github.io/oneWeek/

 

React App

 

juhee067.github.io

 

[App.js]

// 최상위에서 호출해야함
import { useState } from "react";
import "./App.css";
import "./css/reset.css";
import "./css/common.scss";
import Header from "./component/Header";
import View from "./component/View";
import List from "./component/List";

function App() {
  // component 데이터 전달에서의 어려움이 있었다.
  // 게시물의 제목과 내용을 아예 밖으로 빼서 props로 전달

  let [posting, setPosting] = useState([
    {
      id: 0,
      title: "첫 게시물 제목",
      content: "내용",
      good: "0",
      isOn: false,
      isPutOn: false,
    },
  ]);

  const [postId, setPostId] = useState(posting.length);
  // list
  let [list, setList] = useState(false);

  return (
    <div>
      <Header
        posting={posting}
        setPosting={setPosting}
        postId={postId}
        setPostId={setPostId}
        list={list}
        setList={setList}
      />
      <div className="content">
        <View posting={posting} setPosting={setPosting} />
        {list === true ? (
          <List posting={posting} setPosting={setPosting} />
        ) : null}
      </div>
    </div>
  );
}

export default App;

[Header.js]

import React from "react";
import { useState } from "react";
import Modal from "./Modal";

const Header = (props) => {
  // newPost
  let [post, setPost] = useState(false);

  const newPost = () => {
    // post의 값이 클릭할 때마다 반대가 되도록
    setPost(!post);
  };
  //
  let copyData = [...props.posting];
  let copyList = props.list;

  const newGoodArray = () => {
    props.setList(!copyList);
    console.log(copyData);
    let newCopyData = copyData.filter((item) => {
      return item.good > 0;
    });
    props.setPosting(newCopyData);
  };

  const newStarArray = () => {
    props.setList(!copyList);
    let newCopyData = copyData.filter((item) => {
      return item.isOn === true;
    });
    props.setPosting(newCopyData);
  };

  return (
    <div className="header">
      <div className="container">
        {" "}
        {/* -----모달창이 떴을 때 새 게시물 버튼은 실행 안되도록----- */}
        <button
          onClick={() => {
            newPost();
          }}
        >
          새 게시물
        </button>
        <button
          onClick={() => {
            newGoodArray();
          }}
        >
          좋아요 모아보기
        </button>
        <button
          onClick={() => {
            newStarArray();
          }}
        >
          즐겨찾기 모아보기
        </button>{" "}
        {/* post true일때 모달이 열린다. modal창의 취소 버튼 클릭시 닫히는 걸 고려하여 함수 전달 */}
        {post === true ? (
          <Modal
            newPost={newPost}
            posting={props.posting}
            setPosting={props.setPosting}
            post={post}
            setPost={setPost}
            postId={props.postId}
            setPostId={props.setPostId}
          />
        ) : null}
      </div>
    </div>
  );
};

export default Header;

[Modal.js]

import React from "react";
import { useState, useRef, useEffect } from "react";

const Modal = (props) => {
  //  if (props.input == "" || props.textarea == "")에서 props.input 이 undefined임
  // 1. 최상단에 console.log(props)했지만 props에 전달된 내용을 보니 원하는 데이터가 전달 되지않음
  // 2. props 전달이 head(부모)에서 오지않고 App(조부모)에서 오고 있었음
  //   3. head(부모)를 거쳐서 와야한다는 것을 알게됨
  // 4. App(조부모)에서 head(부모)에 props를 전달하고 modal(자식)로 props를 전달하니 원하는 데이터를 받을 수 있었음
  //5. 지금 굉장히 구조가 잘못된 선택을 한 것 같다. 빨리 리덕스 툴킷을 배우고 싶다
  const titleInputRef = useRef();
  const textareaInputRef = useRef();

  let [input, setInput] = useState("");
  let [textarea, setTextarea] = useState("");
  const chageId = () => {
    let copyId = props.postId;
    copyId++;
    props.setPostId(copyId);
  };
  const addContent = () => {
    if (input === "") {
      alert("입력해주세요");
      return titleInputRef.current.focus();
    }
    if (textarea === "") {
      alert("입력해주세요");
      return textareaInputRef.current.focus();
    }

    let copyData = [...props.posting];

    copyData.unshift({
      id: props.postId,
      title: input,
      content: textarea,
      good: "0",
      isOn: false,
      isPutOn: false,
    });

    props.setPosting(copyData);

    let copyModal = props.post;
    props.setPost(!copyModal);
  };

  useEffect(() => {
    titleInputRef.current.focus();
  }, []);
  return (
    <div className="modal">
      <div className="title">
        <input
          maxlength="6"
          placeholder="제목"
          ref={titleInputRef}
          value={input}
          onChange={(e) => {
            setInput(e.target.value);
          }}
        ></input>
      </div>
      <div className="writing">
        {" "}
        <textarea
          ref={textareaInputRef}
          value={textarea}
          placeholder="글쓰기"
          cols="70"
          rows="15"
          onChange={(e) => {
            setTextarea(e.target.value);
          }}
        ></textarea>
        <button
          className="writingBtn"
          onClick={() => {
            chageId();
            addContent();
          }}
        >
          글쓰기
        </button>
        <button
          onClick={() => {
            props.newPost();
          }}
        >
          취소
        </button>
      </div>
    </div>
  );
};

export default Modal;

[View.js]

import React from "react";
import { FaRegTimesCircle, FaRegThumbsUp, FaRegStar } from "react-icons/fa";
const View = (props) => {
  //  goodBtn

  const goodBtn = (index) => {
    let copy = [...props.posting];
    copy[index].good++;
    props.setPosting(copy);
  };
  //즐겨찾기 구현
  const checkStarBtn = (a) => {
    let copy = [...props.posting];
    const mathId = copy.find((el) => el.id === a);

    mathId.isOn = !mathId.isOn;
    // isOn이 true일 때 class 'on'을 붙이고 아니면 떼라

    props.setPosting(copy);
  };
  // 게시물 삭제
  // 1. 데이터 가지고 오기
  // 2. 선택한 배열 삭제하기 [splice() ]

  const deletePosting = (id) => {
    // 배열 삭제되는 거랑 on 붙는 거랑 중첩되는 거 어떻게 하지..?
    let copy = [...props.posting];
    // copy[id].isPutOn = !copy[id].isPutOn;
    copy.splice(id, 1);

    props.setPosting(copy);
  };
  

  return (
    <div className="view">
      <div className="container">
        {" "}
        {props.posting.map((a, index) => {
          return (
            <div
              className={`sub ${a.isPutOn === true ? "on" : null}`}
              key={props.posting.id}
            >
              <div className="top">
                <div className="contentNum">
                  <span>{a.id + 1}</span>
                  <span>1월 1일</span>
                </div>

                <span>
                  <FaRegTimesCircle
                    onClick={() => {
                      deletePosting();
                    }}
                  />
                </span>
              </div>
              <div className="main">
                <div className="mainContent">
                  {" "}
                  <span className="title">{a.title}</span>
                  <span>{a.content}</span>
                </div>
                <div className="icon">
                  {" "}
                  <div className="good">
                    <FaRegThumbsUp
                      onClick={() => {
                        goodBtn(index);
                      }}
                    />
                    <span className="goodCount">
                      {props.posting[index].good}
                    </span>
                  </div>
                  <div className="find">
                    <FaRegStar
                      className={`checkStar ${a.isOn === true ? "on" : null}`}
                      onClick={() => {
                        // 에러가 발생한 지점에서 코드를 더 실행하지않고 이후는 멈춰버린다.

                        checkStarBtn(a.id);
                      }}
                    />
                  </div>
                </div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default View;