20210307 19일차 그림판/일기장 로직 구현(85% 완성)

2021. 3. 7. 20:23·BootCamp_Codestates/Final Project

수도 로직

Paint Page: 그림그리기 완료 여부를 상태끌어올리기로 app 으로 올리고 diary 페이지에 props로 전달.

- Diaryinfo component: 날씨 정보 저장 및 상태끌어올리기로 page 로 전달

- Title: isLogin 상태에 따라 (손님) 의 행복한 하루 또는 (유저이름) 의 행복한 하루 로 구현

- Cpaint component: 그림의 좌표 데이터/url 을 저장하고 이를 diary 에 전달.

 

실제 구현

1. 로그인, 로그아웃, 회원가입 코드 리팩토링. 로그인 상태를 최상위의 app.tsx 에서 관리

로그인, 로그아웃 로직과 회원가입 로직은 이미 끝낸 상태였지만,

회원가입 후 자동 로그인된 상황에서 로그아웃을 했을때 메인페이지의 작동이 잘 안되는 현상이 발생했다. (로그아웃 했는데 로그아웃 버튼이 존재하고 모든 네이게이션 버튼이 존재하는 상황)

결론적으로는, 부모를 app.tsx 로 두고 로그인, 로그아웃, 회원가입 시 변화하는 로그인 상태를 관리하도록 구현했다.

회원가입을 하면 로그인 상태가 변화하는데 changeSignin 이라는 함수를 이용하여 상태끌어올리기를 한다.

로그인, 로그아웃도 마찬가지로 이 함수를 사용하는데, isSignin 상태를 자식에게 전달하는 점이 다르다. 이는 자식 컴포넌트에서 로그인 유무에 따라 보여줘야 하는 엘리먼트가 다르기 때문에 이 isSignin 이 true 냐 false 냐가 기준이 된다.

function App(): ReactElement {
	const [isSignin, setSignin] = useState(false);
	const [weatherData, setWeatherData] = useState("");
	const [imgUrl, setImgUrl] = useState("");
	const [imgData, setImgData] = useState("");

	const changeSignin = (e: boolean) => {
		console.log(e);
		setSignin(e);
	};
	const changeWeather = (e: string) => {
		// console.log(e);
		setWeatherData(e);
	};
	const changeImgUrl = (e: string) => {
		// console.log(e);
		setImgUrl(e);
	};
	const changeImgData = (e: string) => {
		// console.log(e);
		setImgData(e);
	};

	return (
		<Router>
			<Main>
				<Switch>
					<Route exact path="/">
						<Manual />
						<SignIn changeSignin={changeSignin} isSignin={isSignin} />
					</Route>
					<Route exact path="/signup">
						<Manual />
						<Application changeSignin={changeSignin} />
					</Route>
					<Route exact path="/creatediary">
						<Paint changeWeather={changeWeather} changeImgUrl={changeImgUrl} changeImgData={changeImgData} />
						<Diary weatherData={weatherData} imgUrl={imgUrl} imgData={imgData} />
					</Route>

2. 그림판, 일기장 로직 구현

그림판 컴포넌트에서 날씨 데이터, 이미지 url, 이미지 좌표 데이터를 diary 페이지에 전달하는데, 이는 모든 데이터가 제출되었을 때 diary 의 완료버튼이 작동할 수 있도록 하기 위해서이다. 즉, 이 데이터들을 상태끌어올리기 및 diary 에 전달하고,

diary 에서의 제목, 내용 작성, 기분 까지 선택되었을 때 완료버튼이 작동하여 서버에 API 를 통해 제출하게 된다.

 

예) 다이어리에 그림판 데이터를 전달하는 코드

interface paintDataProps {
	weatherData: string;
	imgUrl: string;
	imgData: string;
}

export default function Diary(props: paintDataProps): ReactElement {
	const { weatherData, imgUrl, imgData } = props;
	const history = useHistory();
	const [isPublic, setIsPublic] = useState(false);
	const [title, setTitle] = useState("");
	const [content, setContent] = useState("");
	const [emotion, setEmotion] = useState("");

예) 완료버튼을 눌렀을때 작동하는 제출코드. 그림 완료 버튼을 눌러야 이미지 url 과 좌표데이터가 전달된다.

	const handleSubmit = async () => {
		if (weatherData === "") {
			console.log("날씨를 선택해주세요");
		} else if (imgUrl === "" || imgData === "") {
			console.log("그림 완료 버튼을 누르세요");
		} else if (title === "") {
			console.log("제목을 써주세요");
		} else if (content === "") {
			console.log("내용을 써주세요");
		} else if (emotion === "") {
			console.log("기분을 선택해주세요");
		}
		return;
		await axios.post("https://royal-diary.ml/contents/ccontent", {

3. 그림 PNG 이미지 multer 에 송부 및 이미지 URL 리턴 작동

관련코드는 아래와 같다. 비동기로 받아오기 때문에 하나하나 변수에 담아 리턴하는 방식으로 구현했다. 이해가 편하다.

diary 페이지에 전달하는 그림 데이터는 2가지이다.

  1. multer 로 S3 버켓에 그림을 업로드하고 리턴받는 Image Url => 일기보기 page 에서 사용

  예) royaldiarymulter.s3.ap-northeast-2.amazonaws.com/1616116451513

  2. 그림의 좌표데이터 => 그림 수정시 사용(되돌리기 기능이 가능)

  예)

	async function dataURLtoFile(dataurl: string) {
		const blobBin = atob(dataurl.split(",")[1]); // base64 데이터 디코딩
		const array = [];
		for (let i = 0; i < blobBin.length; i += 1) {
			array.push(blobBin.charCodeAt(i));
		}
		const u8arr = new Uint8Array(array);
		const file = new Blob([u8arr], { type: "image/png" }); // Blob 객체 생성
		const formdata = new FormData(); // formData 생성
		formdata.append("img", file); // formdata에 file data 추가
        // axios 로 서버에 img 파일 보내기
		// 유알엘을 리턴하여 saveAsPNG 에서 사용할 수 있도록!!
		const imgUrl = await axios
			.post("https://royal-diary.ml/image", formdata, {
				headers: { "content-Type": "multipart/form-data" },
			})
			.then((res) => {
				const returnedUrl = res.data.imgUrl;
				return returnedUrl;
			})
			.catch((err) => {
				console.log("server error occured");
			});
		return imgUrl;
	}
	const saveAsPNG = async () => {
		const canvas = document.querySelector(".CanvasDraw canvas:nth-child(2)") as HTMLCanvasElement;
		const imgUrl = canvas.toDataURL("image/png");//canvas Element 에 그려진 내용을 Data URL로 변환
		const returnedUrl = await dataURLtoFile(imgUrl);//S3버켓에 파일업로드 및 이미지URL을 받는 메소드로 Data URL 전달
		// 서버로부터 리턴받은 url 을 handleSaveClick 에 전달
		return returnedUrl;

		/* 이미지 데이터로 원하는 이미지 엘리먼트에 이미지를 만들 수 있다.
		const newImage = document.createElement("img");
		newImage.src = image;
		document.querySelector(Main)?.append(newImage);
		*/
		/* 이미지 파일을 다운받을수 있다. 
		 downloadImage(image, "my-canvas.png");
		*/
	};

	/* 이미지 파일 다운받는 함수 
	function downloadImage(data: string, filename: string) {
		const a = document.createElement("a");
		a.href = data;
		a.download = filename;
		document.body.appendChild(a);
		a.click();
	}
	*/
	const handleSaveClick = async () => {
		const data = firstCanvas.current.getSaveData();//그림의 좌표데이터
		setImgData(data);//상태(좌표데이터)끌어올리기
		const imgUrl = await saveAsPNG();
		setImgUrl(imgUrl);//상태()끌어올리기
		// multer 에 전송후 받은 url 과 좌표 데이터를 sessionStorage 에 저장해서 글쓰기 완료 버튼을 눌렀을때 사용한다..!
	};

시행착오

처음엔 기존에 있던 코드가 아깝다(?)는 마음이 들어서인지, signin page 에 있는 로그인 상태를 사용하여 구현을 시도했다.

하지만, 생각처럼 작동하지가 않았다. 특히, props 가 닿지 않은 곳은 sessionStorage 데이터를 사용하여(props 로 구현하기전, 그림판 데이터들을 이 세션스토리지에 담아 다이어리에 전달하고자 했다.) 해결하려고 했지만, 새로고침이 되어야 다이어리에서 이 데이터들을 읽을 수 있는 문제가 있었다. 그렇다고 새로고침을 하면 다이어리의 내용들이 모두 사라진다.

그래서 결국 최상위에 위치하는 app.tsx 에 로그인 상태를 두었고, 몇가지 함수들을 만들어 그림판 데이터를 다이어리에 전달해 줄 수 있었다.

세션 데이터는 참 좋은 것이지만, 실시간으로 반영하는 것이 불가하다. 관련하여 이 세션 데이터를 사용하는 useEffect 함수에 대해 더 공부가 필요하다.  코드 상 리뷰할 내용이 더욱 많지만, 너무 많아서 추후 정리하도록 한다.

 

도움 받은 사이트

multer 로 이미지 업로드하기: www.zerocho.com/category/NodeJS/post/5950a6c4f7934c001894ea83

useEffect 사용하기

1) deps 파라미터: react.vlpt.us/basic/16-useEffect.html

2) 공식 문서 번역: medium.com/@dayong/%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%9B%85-react-hooks-3-useeffect-6b781a6c6769

3) handle API calls using async await with the useEffect hook: javascript.plainenglish.io/handling-api-calls-using-async-await-in-useeffect-hook-990fb4ae423

4) 여러개의 input 상태관리 하기 (사용하진 않았지만.): velog.io/@zwonlala/Hook-setState-React%EC%97%90%EC%84%9C-%EC%97%AC%EB%9F%AC%EA%B0%9C%EC%9D%98-input-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0

Specifying onClick event type with Typescript and React.Konva:

stackoverflow.com/questions/45089866/specifying-onclick-event-type-with-typescript-and-react-konva/45092365

'BootCamp_Codestates > Final Project' 카테고리의 다른 글

20210309 21일차 그림일기장 수정 로직 구현  (0) 2021.03.10
20210308 20일차 그림판/일기장 로직 구현(99% 완성)  (0) 2021.03.09
20210306 18일차 로그인/로그아웃 로직 구현 완료  (0) 2021.03.07
20210305 17일차 회원가입 로직 구현 완료  (0) 2021.03.06
20210304 16일차 회원가입 로직 구현(미완)  (0) 2021.03.04
'BootCamp_Codestates/Final Project' 카테고리의 다른 글
  • 20210309 21일차 그림일기장 수정 로직 구현
  • 20210308 20일차 그림판/일기장 로직 구현(99% 완성)
  • 20210306 18일차 로그인/로그아웃 로직 구현 완료
  • 20210305 17일차 회원가입 로직 구현 완료
JTB
JTB
웹/앱 개발 정보를 공유하고 있습니다.
  • JTB
    JTechBlog
    JTB
  • 전체
    오늘
    어제
    • All About Programming;) N
      • Computer Science
        • Terminology and Concepts
        • Network
        • Operating System
        • Database
        • Data Structure
      • Frontend
        • Javascript Essentials
        • Perfomance Optimization
        • JS Patterns
        • Next.js
        • Flutter
      • Backend
        • Node.js
      • DevOps
        • Docker & Kubernetes
      • Coding Test N
        • LeetCode N
        • Programmers
      • Tech Books & Lectures
        • Javascript_Modern JS Deep d..
        • Network_IT 엔지니어를 위한 네트워크 입문
      • Projects
        • PolyLingo_2025
        • Build Your Body_2024
        • JStargram_2021
        • Covid19 Tracker_2021
        • JPortfolio_2021
      • BootCamp_Codestates
        • TIL
        • TILookCloser
        • Pre Tech Blog
        • IM Tech Blog
        • Daily Issues and DeBugging
        • First Project
        • Final Project
        • Sprint Review
        • Good to Know
        • Socrative Review
        • HTML &amp; CSS
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 글쓰기
    • 관리
  • 공지사항

  • 인기 글

  • 태그

    Binary Tree BFS
    Network
    이벤트
    Operating System
    커리어
    mobile app
    자바스크립트
    How memory manage data
    자바스크립트 딥다이브
    Data Structure
    polylingo
    DOM
    Shared resources
    VoiceJournal
    프론트엔드 성능 최적화 가이드
    Threads and Multithreading
    CPU scheduling algorithm
    need a database
    Time complexity and Space complexity
    스코프
    JavaScript
    database
    js pattern
    testing
    모던 자바스크립트 Deep Dive
    indie hacker
    leetcode
    structure of os
    TCP/IP
    딥다이브
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
JTB
20210307 19일차 그림판/일기장 로직 구현(85% 완성)
상단으로

티스토리툴바