왓챠피디아의 평점기능을  CU편의점에 접목시킨 프로젝트 watCU가 끝이 났습니다.

 

제가 담당한 부분은 Detail(상품 상세 페이지)와 Star(별점/별점그래프)이였습니다.

 

그 기념으로 기억에 남는 기능과 느낀점을 간단히 적어볼까 합니다.

 

 

기억에 남는 기능 소개

 

 

 

<Slider>

 

React로 제대로 된 기능을 만들어 보는건 슬라이더 기능이 처음이었습니다.

구글로 검색해 본 대부분의 결과는 라이브러리로 만든 결과물이 대부분이었고 간혹가다 있는 라이브러리 없이 만든 영상은

function으로 만든 영상이였습니다.

 

그래서 저는 바닐라 JS로 해당 기능을 구현하는 영상을 보고 그것을 React로 옮겨야겠다고 생각했습니다.

그 과정에서 수많은 고뇌와 오류를 맞이했지만 끝끝내 그것을 구현하는데 성공했습니다.

 

그 후 멘토님에게 리뷰를 받고 리팩토링 과정을 거치며 코드를 한층 더 간결하게 작성할 수 있었습니다.

 

before

handleNextSlider = () => {
    const sliderElement = this.sliderRef.current;
    const itemElement = this.itemRef.current;
    const itemWidth = Math.ceil(itemElement.getBoundingClientRect().width);
    if (
      this.state.transFormPosition ===
      (sliderElement.getElementsByClassName('anotherItem').length - 4) *
        -itemWidth
    ) {
      return;
    }

    this.setState(
      {
        transFormPosition: this.state.transFormPosition - itemWidth,
      },
      () => {
        sliderElement.style.transform = `translate(${this.state.transFormPosition}px)`;
      }
    );
  };

 

after

  handleNextSlider = () => {
    const sliderElement = this.sliderRef.current;
    const { currentIndex } = this.state;
    const { subImage } = this.props;

    if (this.itemRef.current) {
      const itemWidth = Math.ceil(
        this.itemRef.current.getBoundingClientRect().width
      );
      if (currentIndex === subImage - 4) {
        return;
      }

      this.setState(
        {
          currentIndex: currentIndex + 1,
        },
        () => {
          sliderElement.style.transform = `translate(-${
            this.state.currentIndex * itemWidth
          }px)`;
        }
      );
    }
  };

getBoundingClientRect().width 매서드를 사용하여 일부러 px를 지정하지 않아도 그 너비에 맞게

슬라이드의 요소가 넘어가도록 설정하였습니다.

 

그리고 Refactoring을 통해서 복잡한 계산식을 통하여 슬라이더의 위치를 계산하는 대신 Index 정보를 이용하여 보기 쉽고

직관적이도록 변경하였습니다.

 

 

별점/별점그래프

<Star>

 

<StarGraph>

 

 

별점 기능과 별점그래프를 실시간으로 연동시키는 것은 그 과정은 어려웠지만 하나하나 원하는 대로 코드가 구현될 때 마다

매우 즐거웠습니다. 

난생 처음으로 백엔드에게 데이터를 받고 또 post를 이용하여 보내고 그 과정이 그래프라는걸 통해서 유의미한 결과물이 나오는 것은 

 

'아, 내가 정말로 백엔드와 통신을 하는중이구나!' 

 

라는 감상이 들게 만들게 만들었습니다.

제가 실시간 연동을 한 방법은 다음과 같았습니다.

 

<Detail.js(부모컴포넌트)>

export default class Detail extends Component {

  constructor() {
    super();
    this.state = {
      userInfo: [], 
    };
  }

callStarGraphApi = () => {
    fetch(
      `${BASE_URL}/ratings/products/${this.props.match.params.productId}/graph`
    )
      .then(res => res.json())
      .then(data =>
        this.setState({
          userInfo: data.results,
        })
      );
  };

componentDidMount = () => {
    this.callStarGraphApi();
  };

render(){
  return{
    <StarRating callStarGraphApi={this.callStarGraphApi}>                  
    <StarGraph userInfo={this.state.userInfo} />
  }
}

처음 rating에 대한 정보를 컴디마를 통하여 userInfo state에 저장합니다.

그 다음 자식컴포넌트들인

StarRating에 Api호출 함수 callStarGraphApi를 props로 주고

StarGraph에 userInfo를 props로 줍니다.

 

 

<StarRating.js>

export default class StarRating extends Component {
  constructor() {
    super();
    this.state = {
      rateValue: [false, false, false, false, false]
    };
  }


handleStarClick = clickedIndex => {
    const prevRateValue = [...this.state.rateValue];
    const isClickedStarActive = prevRateValue[clickedIndex];
    const isNextStarActive = prevRateValue[clickedIndex + 1];

    if (isClickedStarActive && isNextStarActive) {
      prevRateValue.fill(false, clickedIndex + 1);
    } else if (isClickedStarActive) {
      prevRateValue.fill(false, 0, clickedIndex + 1);
    } else if (!isClickedStarActive) {
      prevRateValue.fill(true, 0, clickedIndex + 1);
    }

    const rating = prevRateValue.filter(value => value).length;

 
      fetch(`${BASE_URL}/ratings/products/${this.props.id}`, {
        method: 'POST',
        body: JSON.stringify({
          rating: rating,
        }),
        headers: {
          'Content-type': 'application/json; charset=UTF-8',
          Authorization: localStorage.getItem('token'),
        },
      }).then(() => {
        const { callStarGraphApi} =this.props;

        callStarGraphApi();
      });

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });
    
  };

별점을 클릭시 (여기서는 3점을 줬다고 하겠습니다.)

[true, true, true ,false ,false]가 나오게 됩니다.

그리고 true 갯수인 3을 fetch함수에서 post로 데이터를 보내게 됩니다.

 

 

이렇게 되면 기존 데이터서버에는 3점이라는 데이터가 하나 더 쌓이게 됩니다.

하지만 아쉽게도 우리는 쌓이기 전의 데이터를 받아 온 상태입니다.

최신상태의 데이터가 아니라는 것입니다.

그러니 다시 이 데이터를 호출해 줄 필요가 있습니다.

 

아까 Detail.js에서 받아온 Api호출 함수 callStarGraphApi를 호출해줍니다.

 

.then(() => {
        const { callStarGraphApi} =this.props;

이제 데이터가 최신상태로 업데이트 됩니다.

이렇게 되면 Detail.js의 this.state.userInfo역시 최신상태로 업데이트 됩니다.

 

 

<StarGraph.js>

export default class StarGraph extends Component {
  render() {
    const ratingValue = this.props.userInfo.map(user => user.rating);

    const totalPerson = ratingValue.filter(ratingPerson => ratingPerson).length;
    const percentageList = ratingValue
      .reduce(
        (preValue, ratingPerson) => {
          if (ratingPerson === 0) {
            return preValue;
          }

          preValue[ratingPerson - 1] += 1;
          return preValue;
        },
        [0, 0, 0, 0, 0]
      )
      .map(ratingPerson => Math.round((ratingPerson / totalPerson) * 100));

    const maxPercentage = Math.max(...percentageList);

    return (
      <>
        <div className="graphLayout">
          <div className="graphContainer">
            {percentageList.map((percent, index) => {
              return (
                <div
                  className={
                    percent >= maxPercentage
                      ? 'maxRatingPerson'
                      : 'ratingPerson'
                  }
                  key={index}
                  style={
                    percent > 0 ? { height: `${percent}%` } : { height: '1%' }
                  }
                ></div>
              );
            })}
          </div>

          <ul className="scoreNumber">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
          </ul>
        </div>
      </>
    );
  }
}

StarGraph는 reduce함수를 이용하여 각 별점의 평가자 수를 반영하도록 하였습니다.

그 다음 각 별점의 평가자 수를 전체 평가자의 수로 나눈 후 곱하기 100을 하여 백분율로 나타낸 겁니다.

 

이제 예제를 통해 설명해보겠습니다.

 

별점 1점: 2명 → 약22%

별점 2점: 1명 → 약11%

별점 3점: 2명 → 약22%

별점 4점: 2명 → 약22%

별점 5점 : 2명 → 약22%

 

총 9명이 다음과 같이 평가하였습니다.

이때 유저A가 평점을 3점을 새로이 추가했다고 합시다.

그러면 실시간 업데이트된 데이터가 StarGraph로 내려옵니다.

그렇다면...

 

별점 1점: 2명 → 20%

별점 2점: 1명 → 10%

별점 3점: 3명 → 30%

별점 4점: 2명 → 20%

별점 5점 : 2명 → 20%

 

이렇게 그래프가 변합니다.

이제 이렇게 변하는 그래프에 반응하도록 CSS로 애니메이션까지 주면 완성입니다.

 

 

프로젝트 후 느낀점

 

 

 

watCU는 제가 다른 사람들과 '협업'을 통해 완성한 최초의 프로젝트입니다.

그렇기 때문인지 그 완성본을 봤을 때의 신기함과 기쁨은 정말 낯선 것이었습니다. 

 

본래 모든 일을 혼자서 처리하는 것을 선호했기 때문에 다른 사람을 믿고 일을 맡기는 건 처음엔 불안하고 걱정되기 마련이었습니다.

그러나 점차 시간이 지나고 프로젝트의 형태가 갖춰지면서

 

제가 지녔던 생각은 너무나도 편협하고 좁은 것이라는 것을 깨달을 수 있었습니다. 

 

모두 자기가 맡은 바에 충실하며 기한을 지키기 위해 애쓰고 혼자서 끙끙대며 앓아가며 코드를 작성하는 것보다는 서로 협력하며 알고 있는 지식은 베풀고 모르는 지식은 가르침 받는 문화는 너무나도 신선하고 충격적이였습니다.

 

그리고 끝끝내 많은 고뇌와 조언으로 탄생한 우리의 프로젝트를 다같이 모여서 보는 순간 

 

이 프로젝트는 '내가 만든 프로젝트'가 아닌 '우리가 만든 프로젝트'라는게 마음 속에 깊이 새겨졌습니다.

 

앞으로 개발자로 살아가게 되면서 가장 걱정했던 것은 협업이였지만

 

이제는 개발자로 살아가게 되면서 가장 기대되는 것이 협업으로 변하게 된 정말 인상깊은 프로젝트였다고 생각합니다.

 

 

 

 

 

 

 

 

 

 

'Wecode > Project' 카테고리의 다른 글

[Project-1] watCU - 슬라이더  (0) 2021.09.12
[Project-1] watCU - 별점,별점그래프  (0) 2021.09.12

 

 

 

이 코드는 백엔드와의 데이터 통신을 고려하지 않고 짜여진 코드입니다.

 

백엔드와의 데이터 통신을 고려하여 짜여진 코드는 추후 별점 그래프와 함께 추가될 예정입니다.

 

즉, 이 코드는 순수 별점기능만을 보여줍니다.

 

 

 

기능은 총 3가지가 있습니다.

 

1. 별을 클릭하면 별점이 매겨지는 기능(마우스 클릭)

2.같은 별점을 다시 클릭하면 취소하기가 되는 기능 ex) 별점 3점을 누른 후 다시 3점을 누르면 별이 모두 회색으로 변합니다.

3.마우스 Hover기능 (마우스 클릭으로 별점 4점을 줬어도 마우스 Hover시 1점~5점 자유롭게 이동가능)

 

 

 

 

<StarRating.js>

import React, { Component } from 'react';
import EachStar from './EachStar/EachStar';
import './StarRating.scss';

export default class StarRating extends Component {
  constructor() {
    super();
    this.state = {
      rateValue: [false, false, false, false, false],
      hoverRateValue: [false, false, false, false, false],
      isHover: false,
    };
  }

  handleStarClick = clickedIndex => {
    const prevRateValue = [...this.state.rateValue];
    const isClickedStarActive = prevRateValue[clickedIndex];
    const isNextStarActive = prevRateValue[clickedIndex + 1];

    if (isClickedStarActive && isNextStarActive) {
      prevRateValue.fill(false, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }

    if (isClickedStarActive) {
      prevRateValue.fill(false, 0, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }

    if (!isClickedStarActive) {
      prevRateValue.fill(true, 0, clickedIndex + 1);

      this.setState({
        isHover: false,
        hoverRateValue: [false, false, false, false, false],
        rateValue: prevRateValue,
      });

      return;
    }
  };

  handleStarMousehover = hoveredIndex => {
  
    const prevRateValue = [...this.state.hoverRateValue];
    const isClickedStarActive = prevRateValue[hoveredIndex];
    const isNextStarActive = prevRateValue[hoveredIndex + 1];

    if (isClickedStarActive && isNextStarActive) {
      prevRateValue.fill(false, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }

    if (isClickedStarActive) {
      prevRateValue.fill(false, 0, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }

    if (!isClickedStarActive) {
      prevRateValue.fill(true, 0, hoveredIndex + 1);

      this.setState({
        isHover: true,
        hoverRateValue: prevRateValue,
      });

      return;
    }
  };

  handleStarMouseout = () => {

    this.setState({
      isHover: false,
      hoverRateValue: [false, false, false, false, false],
    });
  };

  checkIsActive = star => {
    if (this.state.isHover) {
      if (this.state.hoverRateValue[star]) {
        return 'activeStar';
      }

      return 'inactiveStar';
    }

    if (this.state.rateValue[star]) {
      return 'activeStar';
    }

    return 'inactiveStar';
  };

  render() {
    const starArray = [0, 1, 2, 3, 4];

    return (
      <>
        <div className="starList">
          {starArray.map((star, index) => {
            return (
              <button
                key={index}
                onClick={() => this.handleStarClick(star)}
                onMouseEnter={() => this.handleStarMousehover(star)}
                onMouseLeave={() => this.handleStarMouseout()}
              >
                <EachStar size={this.props.size} name={this.checkIsActive(star)} />
              </button>
            );
          })}
        </div>
      </>
    );
  }
}

 

 

<StarRating.scss>

.starList {
  display: flex;

  button {
    fill: grey;
  }
}

 

 

 

 

<EachStar.js>

import React, { Component } from 'react';
import './EachStar.scss';

export default class EachStar extends Component {
  render() {
    return (
      <div className="eachStar">
        <svg
          className={this.props.name}
          height={this.props.size}
          viewBox="0 -10 511.98685 511"
          width={this.props.size}
          xmlns="http://www.w3.org/2000/svg"
        >
          <path d="m510.652344 185.902344c-3.351563-10.367188-12.546875-17.730469-23.425782-18.710938l-147.773437-13.417968-58.433594-136.769532c-4.308593-10.023437-14.121093-16.511718-25.023437-16.511718s-20.714844 6.488281-25.023438 16.535156l-58.433594 136.746094-147.796874 13.417968c-10.859376 1.003906-20.03125 8.34375-23.402344 18.710938-3.371094 10.367187-.257813 21.738281 7.957031 28.90625l111.699219 97.960937-32.9375 145.089844c-2.410156 10.667969 1.730468 21.695313 10.582031 28.09375 4.757813 3.4375 10.324219 5.1875 15.9375 5.1875 4.839844 0 9.640625-1.304687 13.949219-3.882813l127.46875-76.183593 127.421875 76.183593c9.324219 5.609376 21.078125 5.097657 29.910156-1.304687 8.855469-6.417969 12.992187-17.449219 10.582031-28.09375l-32.9375-145.089844 111.699219-97.941406c8.214844-7.1875 11.351563-18.539063 7.980469-28.925781zm0 0" />
        </svg>
      </div>
    );
  }
}

 

<EachStar.scss>

.eachStar {
  .inactiveStar {
    fill: #eeeeee;
  }

  .activeStar {
    fill: #ffc107;
  }
}

 

 

 

 

 

 

'React > Today I learned' 카테고리의 다른 글

[React] useEffect hook  (0) 2021.12.14
[React] hook, props, state, event + batch  (0) 2021.12.10
fetch함수를 이용한 로그인&회원가입  (0) 2021.07.02
state,props,event  (0) 2021.07.01
Sass  (0) 2021.06.30

 

 

 

 

const array = [1,2,3,4,5]

const arrayReduce = array.reduce(function(){}, initialValue)

 

reduce매서드

 

첫번째 인자: 콜백함수(Arrow function도 가능)

 

두번째 인자: 처음값

 

 

const array = [1,2,3,4,5]

const arrayReduce = array.reduce((accumulator, currentValue) => {}, initialValue)

 

함수에 들어오는 인자

 

첫번째 인자(accumulator): 콜백함수의 반환값(return) 누적

                                                // 첫번째로 들어오는 값은 initialValue가 들어옵니다. 

                                                // initialValue가 없다면 배열의 첫번째 요소가 들어갑니다.

 

두번째 인자(currentValue): 처리 할 현재값

                                                //  initialValue가 있다면 배열의 첫번째 요소부터 들어갑니다. 

                                                //  initialValue가 없다면 배열의 두번째 요소부터 들어갑니다.              

 

 

 

const array = [1,2,3,4,5]

const arrayReduce = array.reduce((accumulator, currentValue) => {
  return accumulator + currentValue
}, 0)

console.log(arrayReduce) // 15

 

initialValue = 0

 

첫번째 사이클

(0,1) => return 0 + 1

 

두번째 사이클

(반환값 0+1이 첫번째 인자로 들어갑니다.)

(1,2) => return 1+2

 

세번째 사이클

(반환값 1+2가 첫번째 인자로 들어갑니다.)

(3,3) => return 3+3

 

네번째 사이클

(6,4) => return 6+4

 

다섯번째 사이클 

(10,5) => return 15

 

 

console.log(arrayReduce)를 하면 15라는 값이 나온다.

 

'JScript > Today I learned' 카테고리의 다른 글

함수형 프로그래밍이란?  (0) 2021.12.05
formData의 값을 console.log로 볼 수 없는 원인  (0) 2021.07.25
TIL#10 Scope !중요  (0) 2021.06.14
TIL#09 UI vs API  (0) 2021.05.09
TIL#08 라이브러리와 프레임워크  (0) 2021.05.09

 

 

 

 

 

 

전체적인 흐름

 

코드로 바로 들어가기 전에 전체적인 흐름을 한 번 짚고 넘어가겠습니다.

 

 

  1. 유저가 이메일을 입력합니다. Email Input의 onChange 함수가 실행 됩니다.
  2. onChange 함수에서 Email Input의 value를 setState를 통해 업데이트 합니다.
  3. 유저가 비밀번호를 입력합니다. Password Input의 onChange 함수가 실행 됩니다.
  4. onChange 함수 안에서 Password Input의 value를 setState를 통해 업데이트 합니다.
  5. Button을 클릭하면 onClick 함수가 실행 됩니다.
  6. onClick 함수 안에서 fetch 함수를 통해 server에 요청(Request)을 보냅니다.
  7. server에서 인증 / 인가 과정을 거친 후의 결과를 응답(Response)으로 보내 줍니다.
  8. 응답의 결과에 따라 Main 페이지로 이동 하거나 에러 메세지를 띄웁니다.

복잡해 보이는 것도 잘게 나눈 다음에 하나씩 차례대로 구현 하면 됩니다.

 

코드

복잡해 보이는 것도 잘게 나눈 다음에 하나씩 차례대로 구현 하면 됩니다.

 

fetch("api주소", {
      method: "POST",
      body: JSON.stringify({
        email: this.state.id,
        password: this.state.pw,
      }),
    })
      .then((response) => response.json())
      .then((result) => console.log("결과: ", result));

 

fetch에 대해서 설명하기 전에 통신을 먼저 해봅시다. api 주소, body의 key 값과 value에 있는 state를 본인의 코드에 맞게 수정해주세요!

fetch 함수 설명

첫 번째 인자는 api 주소, 두 번째 인자는 http 통신에 관한 내용입니다.

두 번째 인자

  • method는 GET, POST, PATCH 등 http method를 입력합니다.
  • JSON 형태로 데이터를 주고 받는데 이 데이터를 body에 넣습니다.
    • 통신을 할 때는 string 형태의 JSON으로 보내야 하기 때문에 JSON.stringify()라는 메서드를 활용해서 포맷을 기존의 Object에서 String으로 변환해줍니다.
  • 통신은 다른 로직에 비해 오래 걸리기 때문에 비동기 처리돼서 then 메서드를 사용합니다.
.then((response) => response.json())

첫 번째 then에서는 server에서 보내준 response를 Object 형태로 변환합니다.

.then((result) => console.log("결과: ", result));

두 번째 then에서는 object로 변환한 response를 console.log로 확인합니다. 여기서 원하는 로직을 구현합니다. 예를 들어

  • 로그인 성공하면 main 페이지로 이동
  • 로그인 실패하면 alert 창에 "아이디나 비밀번호를 확인해주세요." 띄우기

 


 

 

실습

 

 

로그인, 회원가입 기능만을 설명하기 위해 다른 필요없는 기능이 담긴 코드들은 삭제하고 게시함.

 

같은 컴포넌트에서 처음에 회원가입Api로 접근해서 회원가입을 하고

그 후 회원가입 Api를 로그인Api로 바꾼 후 로그인을 시도함.

 

<회원가입>

 

<LoginButton.js>

import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';

class Login_Button extends Component {
  goTomain = () => {
    fetch('회원가입 api주소', {
      method: 'POST',
      body: JSON.stringify({
        email: this.props.idvalue,
        password: this.props.pwvalue,
      }),
    })
      .then(res => res.json())
      .then(result => {
        if (result.message === 'SUCCESS') {
          alret('회원가입 성공!')
        } else {
          alert('회원가입 양식이 틀립니다.');
        }
      });
  };

  render() {
    const { idvalue, pwvalue } = this.props;

    return (
      <div className="button_box">
        <button
          onClick={this.goTomain}
        >
          로그인
        </button>
      </div>
    );
  }
}

export default withRouter(Login_Button);

 

method가 get인 경우 :

1. fetch() 기본은 get이기 때문에 따로 기입하지 않아도 get으로 호출된다.

2. get은 데이터를 받아오는 역할만을 수행한다. 

3. QueryString을 활용해서 데이터를 요청하는 특징이 있다. 이런 특징은 보안에 아주 취약하다.

4. get을 요청할 때 QueryString에 민감하거나 노출이 되면 안되는 값을 노출시키는 행동을 조심해야 한다.

 

method가 post인 경우:

1. method를 따로 기입해줘야 합니다.

2.생성/업데이트하기 위해 서버로 데이터를 보내는데 사용됩니다. 서버에 내가 요청한 데이터를 추가하는

작업을 원할 때 사용합니다.

3.서버로 보내는 데이터는 get방식과 다르게 body에 담아서 보내기 때문에 보안적인 측면에서는

get보다 높다고 할 수 있습니다.

 

둘의 가장 기본적인 차이점은 get요청의 경우에는 사용자에게 필요한 화면에 대한 데이터를 받아오는 역할이라고 한다면 POST는 웹상에서 사용자의 어떤 행동을 Server에 반영하는 일을 한다고 보면 된다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

body는 데이터를 보낼 때 json형태로 보내기 위해 JSON.stringfy() 함수에 객체를 인자로 전달하여 JSON형태로 변환했다.

 

email,pass은 input태그에서 입력하는 값을 부모컴포넌트에서 props로 넘겨주었다.

 

email,password는 백엔드에서 원하는 형식으로 정보를 넘겨줘야 한다.

백엔드 측의 조건에 email에서 @이 포함되어야 하고, password는 8자리이상 이상이라고 하면

그 형식을 지켜줘야 데이터를 성공적으로 보내줄 수 있다는 말이다.

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

첫번째 then 함수에 전달된 인자 res는 http통신 요청과 응답에서 응답의 정보를 담고 있는 객체이다.

그런데 console을 확인해보면 백앤드에서 넘겨주는 응답 body, 즉 실제 데이터는 보이지 않을 것이다. 

응답으로 받는 JSON 데이터를 사용하기 위해서는 res Object 의 json 함수를 호출하고, return 해야한다.

그러면 이 값이 객체 형태로 두 번째 then 함수의 인자(result)로 온다.

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

fetch함수는 비동기 함수이다.

즉, 처리가 완료되기까지 시간이 오래걸리기 때문에 fetch가 끝나기 전에 다른 함수가 먼저 실행될 수 있다.

그렇게 되면 순서가 섞을 수 있기 때문에 .then을 사용하여 순서를 고정시키는 것이다.

 

fetch함수 -> fetch가 다 끝나면 첫번째 .then -> 첫번째가 끝나면 두번째 .then

 

 

 

 

<로그인>

<LoginButton.js>

import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';

class Login_Button extends Component {
  goTomain = () => {
    fetch('로그인 Api', {
      method: 'POST',
      body: JSON.stringify({
        email: this.props.idvalue,
        password: this.props.pwvalue,
      }),
    })
      .then(res => res.json())
      .then(result => {
        if (result.message === 'SUCCESS') {
          this.props.history.push('/main');
          window.localStorage.setItem('token', result.token);
        } else {
          alert('잘못된 회원정보입니다.');
        }
      });
  };

  render() {
    const { idvalue, pwvalue } = this.props;

    return (
      <div className="button_box">
        <button
          onClick={this.goTomain}
        >
          로그인
        </button>
      </div>
    );
  }
}

export default withRouter(Login_Button);

백엔드에서 

회원가입 Api는 데이터 추가가 가능하게 해뒀고 

로그인 Api는 데이터 조회만 가능하게 해뒀다.

 

로그인Api에서 데이터 조회에 사용자 정보가 일치하면 this.props.history.push('/main');으로  메인페이지로 이동하게 하고

백엔드에서 보낸 토큰을 스토리지의 로컬세션에 저장해둔다.

 

정보가 틀리면 '잘못된 회원정보입니다.'가 나온다.

 

 

 

 

 

 

 

'React > Today I learned' 카테고리의 다른 글

[React] hook, props, state, event + batch  (0) 2021.12.10
리액트 매우 쉬운 별점기능 구현  (0) 2021.07.11
state,props,event  (0) 2021.07.01
Sass  (0) 2021.06.30
Router  (0) 2021.06.29

+ Recent posts