Django 프로젝트02 - 리액트와 SPA 방식으로 인스타그램 만들기(8)
2020년08월20일에듀캐스트 장고&리액트 강의를 듣고 정리하는 글이다.
장고에 JWT 토큰 발급 붙이기
import React, { useState, useEffect } from "react";
import { Card, Form, Input, Button, notification } from "antd";
import { SmileOutlined, FrownOutlined } from "@ant-design/icons";
import { useHistory } from "react-router-dom";
import Axios from "axios";
import useLocalStorage from "utils/useLocalStorage";
export default function Login() {
const history = useHistory();
const [jwtToken, setJwtToken] = useLocalStorage("jwtToken", "");
const [fieldErrors, setFieldErrors] = useState({});
const onFinish = (values) => {
async function fn() {
const { username, password } = values;
setFieldErrors({});
const data = { username, password };
try {
const response = await Axios.post(
"http://localhost:8000/accounts/token/",
data
);
const {
data: { token: jwtToken },
} = response;
setJwtToken(jwtToken);
console.log("jwtToken :", jwtToken);
notification.open({
message: "로그인 성공",
icon: <SmileOutlined style= />,
});
// history.push("/accounts/login"); // TODO: 이동 주소
} catch (error) {
if (error.response) {
notification.open({
message: "로그인 실패",
description: "아이디/암호를 확인해주세요.",
icon: <FrownOutlined style= />,
});
const { data: fieldsErrorMessages } = error.response;
// python: mydict.items()
setFieldErrors(
Object.entries(fieldsErrorMessages).reduce(
(acc, [fieldName, errors]) => {
/// errors : ["m1", "m2"].join(" ") => "m1 m2"
acc[fieldName] = {
validateStatus: "error",
help: errors.join(" "),
};
return acc;
},
{}
)
);
}
}
}
fn();
};
return (
<Card title="로그인">
<Form
{...layout}
onFinish={onFinish}
// onFinishFailed={onFinishFailed}
>
<Form.Item
label="Username"
name="username"
rules={[
{ required: true, message: "Please input your username!" },
{ min: 5, message: "5글자 입력해주세요." },
]}
hasFeedback
{...fieldErrors.username}
{...fieldErrors.non_field_errors}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[{ required: true, message: "Please input your password!" }]}
{...fieldErrors.password}
>
<Input.Password />
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</Card>
);
}
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
const tailLayout = {
wrapperCol: { offset: 8, span: 16 },
};
// https://usehooks.com/useLocalStorage/
import { useState } from "react";
export default function useLocalStorage(key, initialValue) {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState(() => {
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error also return initialValue
console.log(error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = value => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value;
// Save state
setStoredValue(valueToStore);
// Save to local storage
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
return [storedValue, setValue];
}