오늘은 리액트에 오류가 발생했을때 어떻게 처리할 지 한번 알아보자
여기서 오류는 api서버에서 받은 오류 메세지 일수도 있고, 리액트에서 캐치한 오류일수도 있다.
처리방식을 간단히 설명하면 오류 발생시 오류발생여부를 체크하여 오류발생여부가 true이면 정의한 에러 컴포넌트에 에러정보를 셋팅해서 보내주면 에러 컴포넌트에서는 모달창으로 오류발생여부를 보여준다.
여기서는 함수형 컴포넌트에서 처리하는 방식이다. 클래스형 함수에서는 ErrorBoundary를 사용해서
componentDidCatch and getDerivedStateFromError 를 이용한 에러 처리방식이 있다. 하지만 hook에서는 아직 제공하지 않고 있다고 한다.
ko.reactjs.org/docs/error-boundaries.html
stackoverflow.com/questions/60537645/how-to-implement-error-boundary-with-react-hooks-component
다음 순서로 작업을 해보자
1. 모달창 오류 컴포넌트를 작성
2. 오류 발생시 오류처리를 위한 useState를 이용한 셋팅
3. 오류 발생하는 부분에 error를 캐치하거나 서버의 오류 응답을 확인
4. return함수에 오류 컴포넌트 추가
5. 오류발생을 시켜서 제대로 처리되는지 확인
1. 모달창 오류 컴포넌트를 작성
import {useEffect, useState} from "react";
import ServerErrorModal from "./ServerErrorModal";
import LoginErrorModal from "./LoginErrorModal";
function ErrorComponent({show,setError,message,type}){
const [close, setClose] = useState(show);
useEffect(()=>{
setClose(show)
},[show])
const handleClose = () => {
setClose(false);
setError(false);
return 0;
}
const errorModal = {
server:<ServerErrorModal close={close} handleClose={handleClose} message={message} ></ServerErrorModal>,
login:<LoginErrorModal close={close} handleClose={handleClose} message={message} ></LoginErrorModal>
}
const modal = errorModal[type];
return (
<>
{modal}
</>
)
}
export default ErrorComponent;
LoginErrorModal.js
import {Button, Modal} from "react-bootstrap";
const LoginErrorModal = ({close,handleClose,message}) => {
return (
<Modal show={close} onHide={handleClose}>
<Modal.Header>
<Modal.Title>Login Error</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>로그인 중 오류가 발생하였습니다.</p>
<p>잠시후 다시 접속해주시기 바랍니다.</p>
<p>{message}</p>
</Modal.Body>
<Modal.Footer>
<Button variant={"primary"} onClick={handleClose}>Close</Button>
</Modal.Footer>
</Modal>
)
}
export default LoginErrorModal;
ServerErrorModal.js
import {Button, Modal} from "react-bootstrap";
const ServerErrorModal = ({close,handleClose,message}) => {
return (
<Modal show={close} onHide={handleClose}>
<Modal.Header>
<Modal.Title>Server Error</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>서버에 응답이 없거나, 오류가 발생하였습니다.</p>
<p>잠시후 다시 접속해주시기 바랍니다.</p>
<p>{message}</p>
</Modal.Body>
<Modal.Footer>
<Button variant={"primary"} onClick={handleClose}>Close</Button>
</Modal.Footer>
</Modal>
)
}
export default ServerErrorModal;
두개의 소스가 거의 같아서 하나의 모달만 이용하고 메세지 부분만 별도로 만들어도 될거 같다.
2. 오류 발생시 오류처리를 위한 useState를 이용한 셋팅
const [err, setError] = useState({hasError:false,message:"",type:"server"});
3. 오류 발생하는 부분에 error를 캐치하거나 서버의 오류 응답을 확인
async function handleSubmit(e){
setLoading(true);
await signIn(user).then(response=>{
if(response.status==200){
console.log(response.data);
localStorage.setItem("token",response.data);
setIsRedirect(true);
}else{
setError({
...err,
hasError: true,
message: response.message,
type:"login"});
}
}).catch(ex=>{
console.log(ex)
setError({
...err,
hasError: true,
message: "",
type: "server"})
})
setLoading(false);
}
4. return함수에 오류 컴포넌트 추가
return(
<Container className={"text-center"} fluid>
<ErrorComponent show={err.hasError}
setError={(flag)=>setError(flag)}
message={err.message}
type={err.type}/>
전체 소스
import {Button, Container, Form, NavLink, Spinner} from "react-bootstrap";
import {useState} from "react";
import {signIn} from "../api";
import ErrorComponent from "../error/ErrorComponent";
import {Link, Route} from "react-router-dom";
import {Redirect} from "react-router";
function Signin(){
const [user, setUser] = useState({username:'',password:''})
const [err, setError] = useState({hasError:false,message:"",type:"server"});
const [loading,setLoading] = useState(false);
const [isRedirect, setIsRedirect] = useState(false);
function handleEmail(e){
setUser({...user,username:e.target.value})
}
function handlePassword(e){
setUser({...user,password:e.target.value})
}
async function handleSubmit(e){
setLoading(true);
await signIn(user).then(response=>{
if(response.status==200){
console.log(response.data);
setIsRedirect(true);
}else{
setError({
...err,
hasError: true,
message: response.message,
type:"login"});
}
}).catch(ex=>{
console.log(ex)
setError({
...err,
hasError: true,
message: "",
type: "server"})
})
setLoading(false);
}
return(
<Container className={"text-center"} fluid>
<ErrorComponent show={err.hasError}
setError={(flag)=>setError(flag)}
message={err.message}
type={err.type}/>
<Form className="form-signin">
<h1 className="h3 mb-3 font-weight-normal">Please sign in</h1>
<Form.Group controlId={"formBasicEmail"}>
<Form.Label className="sr-only">Email address</Form.Label>
<Form.Control onChange={handleEmail} type={"email"} placeholder={"Enter email"} required />
<Form.Label className="sr-only">Password</Form.Label>
<Form.Control onChange={handlePassword} type={"password"} placeholder={"Password"} required />
</Form.Group>
<Form.Group controlId={"formBasicCheckbox"}>
<Form.Check type={"checkbox"} label={"Remember me"}/>
</Form.Group>
<Button onClick={handleSubmit} className="btn btn-lg btn-primary btn-block" variant={"primary"} type={"button"} disabled={loading}>
{loading && <span><Spinner
as="span"
animation="border"
size="sm"
role="status"
aria-hidden="true"
/> Sign in...</span>}
{!loading && "Sign in"}
</Button>
<p className={"float-left"}><Link to={"/signup"}>Sign up</Link></p>
<p className="mt-5 mb-3 text-muted">© 2017-2020</p>
</Form>
<Route>
{isRedirect && <Redirect to="/"/>}
</Route>
</Container>
)
}
export default Signin;
5. 오류발생을 시켜서 제대로 처리되는지 확인
'웹개발 > 리액트' 카테고리의 다른 글
리액트 서버 배포시 url 환경 설정하기(.env파일) (0) | 2021.03.17 |
---|---|
리액트 404 Not found page 처리하기 (0) | 2021.03.16 |
리액트 url redirect (0) | 2021.03.16 |
react ant-design 회원 가입 폼 작업 (0) | 2021.03.12 |
react bootstrap form validation 체크 하기 (0) | 2021.03.10 |