主プロジェクトのレビュー



📌プロジェクトの概要

  • クローンコード:既存のWeb計画と設計を参照して、開発に専念するためのサイトを完了するプロジェクト
  • クローンサイト:STAY FOLIO
  • プロジェクト期間:22.03.28~22.004.08(2週間)
  • サイトを選定する際、メンバーと一緒に作成したいサイトを特定するのは難しいので、メンバーと一緒にいくつかのサイトを見て、実現したい機能を話します.
    また、1つのサイトで実現したいさまざまな機能を実現するのに最適なサイトを見つけました.

    📌使用するテクノロジー


    🌞Front-end

    React , Sass , Router , http-proxy-middleware , moment.js

    ☀️Back-end

    Node.js , Express , MySQL , Prisma , Bcrypt , JWT , CORS

    🌝Common

    Git , Github

    📌ロール#ロール#


    🌞Front-end

  • Nav
    ✔ページ上部Nav bar実施2479182
  • Modal
    ✔¥国を選ぶ際に重点的に注目する国選択モデル実施
    ✔️ moment.jsライブラリを使用してカレンダーモードを実装し、チェックインおよびチェックアウト領域を選択したときにこれらの領域を強調表示します.
    ✔Modalウィンドウをクリックすると、バックグラウンドのスクロール防止機能を実現
  • Slide
    ААААААА
  • Token storage
    АААААААААААААА
    ✔¥АААААААААААААА

    ☀️Back-end

  • Signup API
  • Authorization Middleware
    ✔ログインが必要な操作を行う場合はバックエンドフラグを確認し、以下の論理機能
  • を実行する

    📌プロジェクトレビュー


    🔺コミュニケーションと共有


    昨年初めてフロントオンライン講座を通じて個人的なプロジェクトを行ったが、JavaScriptやreactionという言語自体を理解し運用することは難しく、単純に機能実現に多くの困難に直面した.個人的なプロジェクトでやるべきことや認識を振り返っても意識していません.
    初めてチームプロジェクトをしたときに感じた個人プロジェクトとの違いの一つは、私だけが現在の進捗状況やホットスポットを理解できるのではなく、すべてのチームメンバーがお互いの仕事状況やホットスポットを最新に更新しなければならないことです.
    特に今回のプロジェクトでは、あるホームページが別のチームメンバーと一緒に作業されました.
    また、お互いの進捗状況や些細な話題が「雪玉効果」のように後で大きな話題にならないように、常にコミュニケーションをとり、すぐに解決しようと努力しているので、あまり問題がないので、一緒にホームページを作ることができます.
    (私の意見を積極的に聞いてくれた鄭敏さん...👍)

    🔺moment.js


    momnet.jsは、既存のJavaScriptのDateオブジェクトよりも所望の形状日付に加工しやすく、抽出に必要な年、月、日または比較日の面で使いやすいため、プロジェクト中に所望の形状のクランプを作成するのに適していると考えられている.
    しかし、今振り返ると残念なことに、プロジェクト期間内に必要な機能を実現するためです.彼はjsライブラリの機能だけを熟知しており、カレンダー機能の実現に忙しい.
    なぜ作るのか、長所や短所は何なのか、そして今のmomnetです.jsの開発は中止された(後に回顧録を書いている間にさらに勉強して知った).開発がなぜ中止されたのかなどの問題がある場合、より深い研究や学習は行われていない.

    🔺読み取り可能コード


    チームプロジェクトを行う過程で、他のチームメンバーが私のコードを表示する必要があることがたくさんあります.私も他のチームメンバーのコードを表示して理解する必要がありますが、他のチームメンバーのコードを表示して理解するのに時間がかかりました.
    突然、他のチームメンバーが私のコードを見たとき、彼らは私のコードを見て、私のコードを理解するのにもっと時間がかかるのではないかと思います.
    それでも,限られた時間で機能の実現に専念するだけであるため,毒性に対する思考をすぐに忘れ,コードの作成に専念して機能を実現する.
    今後のコード実装では,注釈を必要としない可読性の良いコードの作成に努めるが,どのような機能であるかを付加注釈で表すか,あるいはコードのみでは理解し難い場合には付加説明などの練習が必要である.
    (誠意を込めた1600行のsignupページが忘れられません…)

    📌記憶に残るコード


    🥇カスタムカレンダー(with motorm.js)


    import React from 'react';
    import moment from 'moment';
    import style from './TwoCalendars.module.css';
    
      // 상태값 관리 와 구현한 기능은 모두 부모 컴포에서 관리해주고
      // 여기서는 받아온 값으로 달력을 보여주는 기능만 존재합니다.
    function TwoCalendars({
      stateMoment,
      checkIn,
      checkOut,
      onCheck,
      tempoCheckOut,
      onHover,
      onHoverReset,
    }) {
      // 달력 생성을 위한 변수
      const thisMonth = stateMoment;
      const thisFirstWeek = thisMonth.clone().startOf('month').week();
      const thisLastWeek =
        thisMonth.clone().endOf('month').week() === 1
          ? 53
          : thisMonth.clone().endOf('month').week();
    
      const nextMonth = stateMoment.clone().add(1, 'month');
      const nextFirstWeek = nextMonth.clone().startOf('month').week();
      const nextLlastWeek =
        nextMonth.clone().endOf('month').week() === 1
          ? 53
          : nextMonth.clone().endOf('month').week();
    
      const checkInDay = checkIn;
      const checkOutDay = checkOut;
      const tempoCheckOutDay = tempoCheckOut;
    
      
      // 특정 날짜마자 어떤 조건에 해당하는지 판단하여 조건에 맞는 className 주는 함수
      const checkDate = days => {
        if (days.format('YYYY-MM-DD') === checkInDay) {
          return style.checkInDay;
        } else if (days.format('YYYY-MM-DD') === checkOutDay) {
          return style.checkOutDay;
        } else if (
          moment(days.format('YYYY-MM-DD')).isBetween(checkInDay, tempoCheckOutDay)
        ) {
          return style.tempoCheckOutDay;
        } else if (
          moment(days.format('YYYY-MM-DD')).isBetween(checkInDay, checkOutDay)
        ) {
          return style.onDay;
        } else {
          return style.days;
        }
      };
    
      const calendarArr = (today, firstWeek, lastWeek) => {
        let result = [];
        let week = firstWeek;
        for (let i = week; i <= lastWeek; i++) {
          result = result.concat(
            <tr key={i}>
              {Array(7)
                .fill(0)
                .map((data, index) => {
                  let days = today
                    .clone()
                    .startOf('year')
                    .week(i)
                    .startOf('week')
                    .add(index, 'day');
                  if (
                    moment().isAfter(days.format('YYYY-MM-DD')) &&
                    moment().format('YYYY-MM-DD') !== days.format('YYYY-MM-DD')
                  ) {
                    return (
                      <td className={style.lastDays} key={index}>
                        <span>{days.format('D')}</span>
                      </td>
                    );
                  } else if (days.format('MM') !== today.format('MM')) {
                    return <td key={index} />;
                  } else {
                    // checkDate 함수의 조건에 따라 다른 className을 부여.
                    return (
                      <td
                        className={`${checkDate(days)}`}
                        onMouseEnter={() => onHover(days.format('YYYY-MM-DD'))}
                        onMouseLeave={onHoverReset}
                        onClick={() => onCheck(days.format('YYYY-MM-DD'))}
                        key={index}
                      >
                        <span>{days.format('D')}</span>
                      </td>
                    );
                  }
                })}
            </tr>
          );
        }
        return result;
      };
    
      return (
        <div className={style.calendarWrapper}>
          {Array(2)
            .fill(0)
            .map((el, idx) => {
              return (
                <div className={style.calendar} key={idx}>
                  <div className={style.month}>
                    {idx === 0
                      ? stateMoment.format('M월')
                      : nextMonth.format('M월')}
                  </div>
                  <table className={style.calendarTable}>
                    <thead className={style.week}>
                      <tr>
                        {['일', '월', '화', '수', '목', '금', '토'].map(
                          (week, idx) => {
                            return (
                              <td className={style.week} key={idx}>
                                {week}
                              </td>
                            );
                          }
                        )}
                      </tr>
                    </thead>
                    <tbody>
                      {idx === 0
                        ? calendarArr(thisMonth, thisFirstWeek, thisLastWeek)
                        : calendarArr(nextMonth, nextFirstWeek, nextLlastWeek)}
                    </tbody>
                  </table>
                </div>
              );
            })}
        </div>
      );
    }
    
    export default TwoCalendars;
    moment.jsを用いてカスタムカレンダーを直接作成した.
    実装された機能の中で、最も多くの時間を費やし、最も印象的で、多くの時間を費やすほど、あなたも喜んでいますが、前の回顧で述べたように、瞬間です.jsに対して正規の学習を行わず,機能の実現のみを重視したのは残念である.
    2つのカレンダーを同時に表示するため、「現在の月」、「来月」に関連する変数を宣言した後、関数を生成する関数で関数を作成して表示します.
    カレンダーを生成するCalendarr関数でjsx構文として配列を使用してhtmlタグに配置すると、次のようなことが起こります.
    cosnt arr = [1, 2, 3, 4, 5];
    // 중략
    return <div>{arr}</div>; // 12345
    特定の日付になるたびに、今日のサイズ基準の前の日付、またはフーバーをクリックしたり、イベントをクリックしたりして、日付のハイライトが表示されるので、最初は、各条件がレンダリングされている場合は、ドアが表示されます.
    その後,判定が不明確なif文によりコードが長くなり,可読性も悪くなったため,classNameを除いて残りのコードを繰り返し,classNameを用いて条件に応じて異なる関数を出力し,classNameを再パッケージし,変更のみが発生するようにした.

    🥈パターンの後ページスクロールを防止


      const [scrollY, setScrollY] = useState(0);
      const [modalActive, setModalActive] = useState(0);
      const modalWhereRef = useRef();
      const modalWhenRef = useRef();
    
      const openModal = e => {
        e.currentTarget.id === 'modal1' 
          ? setModalActive(1) 
          : setModalActive(2);
        setScrollY(window.pageYOffset);
      };
      const closeModal = () => {
        setModalActive(0);
        setScrollY(0);
      };
    
      useEffect(() => {
        if (modalActive === 1) {
          modalWhereRef.current.style.display = 'block';
        } else if (modalActive === 2) {
          modalWhenRef.current.style.display = 'block';
        } else {
          modalWhenRef.current.style.display = 'none';
          modalWhereRef.current.style.display = 'none';
        }
      }, [modalActive]);
    
    useEffect(() => {
        if (modalActive) {
          document.body.style.cssText = `
            top: -${scrollY}px;
            position: fixed; 
            width: 100%;`;
        }
        return () => {
          const scrollY = document.body.style.top;
          document.body.style.cssText = '';
          window.scrollTo(0, parseInt(scrollY || '0') * -1);
        };
      }, [modalActive, scrollY]);
    モードウィンドウがポップアップされると、既存のスクロール可能なページがスクロールされるコードが防止されます.
    ステータス値modalActiveおよびscrollYが変化すると、useEffectが実行される.modlaActiveの状態値が変更されると、現在のスクロール値(scrollY)はbodytopに保存され、bodypositionfixedに変換され、スクロール不可に設定される.そしてwidthの価格を100%に渡し、ページの破壊を防止した.
    モードウィンドウを閉じた場合、useEffectのreturnを使用して、モードウィンドウのアンインストール時にbodyに適用されたcssを既存の状態に復元する.

    モードウィンドウのスクロール防止機能を実装する際に発生する問題


    🔒window.PageYOffsetは問題を適用しません



    次に示すように、スクロールY軸の値を状態値として管理するのではなく、そのままuseEffect内でwindow.pageYOffsetを使用している.
    useEffect(() => {
        if (modalActive) {
          document.body.style.cssText = `
            top: -${window.pageYOffset}px;
            position: fixed; 
            width: 100%;`;
        }
        return () => {
          const scrollY = document.body.style.top;
          document.body.style.cssText = '';
          window.scrollTo(0, parseInt(scrollY || '0') * -1);
        };
      }, [modalActive]);
    スクロールウィンドウを開くと、次のページが既存のページの上部に戻ります.
    useEffect内部では、撮影コンソールであっても、スクロールY軸の値は常にゼロである.
    私個人の問題の原因に対する見方は、modalActiveの状態値が変化するにつれて、ユーザEffectが実行されるとき、外部から値を取得するわけではないので、初期画面がレンダリングされたときにY軸をスクロールする値0だけが含まれ続けると思います.

    🔑トラブルシューティング


    スクロールY軸の状態値も外部で管理します.
    モードウィンドウ実行ボタンを押すと、現在のスクロールY軸の値として保存され、変更した状態値がuseEffectに渡されます.

    🔒navbar消失問題(z-index問題なし)



    モードウィンドウがポップアップされるとnavbaが消えるという問題が発生しました.
    両方とも、positionfixedz-indexの場合、モードウィンドウは1位、navbaは2位である.

    🔑トラブルシューティング


    いくつかのgooglingを通じて、次のことがわかりました.positionfixedの場合、位置指定なしでtopbottomrightleftを使用するとz-indexは適用されません.
    したがって、navbarの位置が正しく指定されていないことが確認され、navbarのtopの値をゼロにすると、正常に動作します.