인프런 커뮤니티 질문&답변

꺼넝님의 프로필 이미지

작성한 질문수

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

Context API와 Reducer를 활용하여 JWT Token 공유하기

로그인 폼을 만들고 로컬 스토리지에 jwt저장하기 강의에서 질문입니다!

해결된 질문

작성

·

629

0

import React, { useState } from "react";
import { Card, Button, Form, Input, notification } from "antd";
import { useHistory } from "react-router-dom";
import Axios from "axios";
import { SmileOutlined, FrownOutlined } from "@ant-design/icons";
import useLocalStorage from "utils/useLocalStorage";

export default function Login() {
  const history = useHistory();
  const [jwtAccessToken, setJwtAccessToken] = useLocalStorage(
    "jwtAccessToken",
    ""
  );

  console.log("loaded Token: ", jwtAccessToken); // 왜 이게 두번이나 출력되는 것이지?

  const onFinish = (values) => {
    async function fn() {
      const { username, password } = values;
      const data = { username, password }; 
      try {
        //응답을 꼭 받아야 한다. 토큰을 받아야 하니까
        const response = await Axios.post(
          "http://127.0.0.1:8000/accounts/token/",
          data,
          { headers: { "Content-Type": "application/json" } }
        );
        // const { data: token } = response; 이런 방식은 아래랑 다르다 response에서 data을 꺼내서 이름을 token이라 짓는 것
        // const token = response.data 와 일치하며 밑에 녀석은
        // const jwtAccessToken = response.data.access 과 일치한다
        const {
          data: { access: jwtAccessToken },
        } = response;
        setJwtAccessToken(jwtAccessToken);

        notification.open({
          message: "로그인 성공!",
          icon: <SmileOutlined style={{ color: "#108ee9" }} />,
        });
        // history.push("/accounts/login"); //TODO: 이동주소
      } catch (error) {
        console.log(error);

        if (error.response) {
          notification.open({
            message: "로그인 실패!",
            icon: <FrownOutlined style={{ color: "#ff3333" }} />,
            description: "아이디/암호를 확인해 주세요.",
            onClick: () => {
              console.log("Notification Clicked!");
            },
          });
        }
      }
    }
    fn(); 
  };

  return (
    <Card title="login">
      <Form
        labelCol={{ span: 8 }} //부트스트랩은 한 행이 12 컬럼인데 antd는 24컬럼임
        wrapperCol={{ span: 16 }}
        style={{ maxWidth: 600 }}
        onFinish={onFinish}
        autoComplete="off"
      >
        <Form.Item
          label="Username"
          name="username"
          rules={[{ required: true, message: "Please input your username!" }]} //rules을 통해 유효성검사로직이 들어가 잇다
        >
          <Input />
        </Form.Item>

        <Form.Item
          label="Password"
          name="password"
          rules={[
            { required: true, message: "Please input your password!" },
            { min: 5, message: "5자리 이상 해주세요" }, // 한글자 한글자 들어갈때마다 검사해준다.
          ]}
        >
          <Input.Password />
        </Form.Item>
        {/* //8칸 이동하고 16칸을 쓰겠다 */}
        <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
          <Button type="primary" htmlType="submit">
            Submit
          </Button>
        </Form.Item>
      </Form>
    </Card>
  );
}

 

안녕하세요 강사님!!

위에서 15번째 줄에 있는 console.log("loaded Token: ", jwtAccessToken);

이 부분이 페이지의 콘솔창에서 두번이나 나타납니다... 왜 그런지 알 수 있을까요??

새로고침을 했을때도 두번 나타나고 submit을 했을 때도 2번 출력됩니다.

아 ! 그리고 simplejwt토큰을 사용중 입니다!스크린샷 2023-02-26 오후 6.25.50.png

답변 1

0

이진석님의 프로필 이미지
이진석
지식공유자

안녕하세요.

Login 함수 컴포넌트 내, 로직은 매 렌더링 시마다 수행이 됩니다.
그러니 현재의 console.log("loaded Token", ...) 도 매 렌더링 시마다 수행이 될 것이구요.

컴포넌트가 re-렌더링되는 것은 그 컴포넌트가 가지고 있는 상탯값이 변경되거나
부모로 부터 전달받은 속성값이 변경될 때 re-렌더링됩니다.

직접적으로 jwtAccessToken 상탯값 변경 이외에 다른 상탯값/속성값 변경이 있을 수도 있습니다.

jwtAccessToken 값의 변경을 탐지하여 console.log 를 수행하실려면
jwtAccessToken 값을 바라보는 useEffect 훅을 만들어보실 수도 있겠습니다.

살펴보시고 또 질문 남겨주세요.

화이팅입니다. ;-)

꺼넝님의 프로필 이미지

작성한 질문수

질문하기