[WebDevCurriculum] React 기반의 file system 구현 - txt/image 불러오기
1. 개요
기존 VanillaJS를 활용하여 filesystem을 구현하는 것에 비해, React 기반의 filesystem은 어떠한 장점이 있는지 살펴본다.
2. 핵심
- file을 local system으로 부터 읽어오고, 이를 상태변수화하여 file load(반영)가 즉시 이루어지도록 한다.
- react-router-dom이 version6로 업데이트되어 props 사용이 안되므로, localStorage를 활용하여 data 저장소를 구성한다.
3. 전체적인 logic
사용자가 로그인을 하면 로그인 정보에 맞춰 data를 유지 및 load 한다.
- 사용자가 ID, PW를 입력하여 로그인한다.
- 로그인을 하면 다른 페이지(Detail)로 넘어간다.
- Detail 페이지에서는 사용자ID 등을 활용하여 데이터를 불러오고 유지한다.
4-1. App.js - routing 구조 구성
Routing 구조를 구성한다.
- react-router-dom version 상향에 따른 준수사항에 맞추어 Routing을 구성한다.
- BrowserRouter(최상위 Routing 계층), Routes, Route 으로 이루어져 있으며, 각 Route는 반드시 Routes component에 포함되어 있어야 한다.
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from '../routes/Home.js';
import Detail from '../routes/Detail.js';
function App() {
return (
<Router>
<Routes>
<Route path="/" exact={true} element={<Home/>} />
<Route path="/:userID" element={<Detail/>}/>
</Routes>
</Router>
);
}
export default App;
4-2. Home.js - 사용자 data 입력 및 localStorage을 활용한 data 전달
사용자가 입력한 data를 localStorage를 임시 저장소로 활용하여 전달한다.
- 여기서의 핵심은 input data를 받고, 이를 상태관리하여 data 변화에 즉시적인 대응(이벤트 감지 등)을 할 수 있게 구성하는 것이다.
- React에서는 VanillaJS와는 달리, component 내부적으로 상태값을 활용하여 함수 인자 등에 활용할 수 있다.
- useState를 사용하여 상태관리선언 > 입력받은 data(value)를 상태변수에 저장
- props를 통한 component 간 data 전달이 불가능하므로, localStorage를 임시적인 data 저장소로 활용한다.
const [userID, setUserID] = useState('');
const [userPW, setUserPW] = useState('');
setUserID(value);
setUserPW(value);
<input type='text' placeholder="ID" value={userID} onChange={updateUserID}/>
<input type='password' placeholder="PW" value={userPW} onChange={updateUserPW}/>
<Link to={{
pathname: `/${userID}`
}} onClick={() => saveStateValues(userID, userPW)}>로그인하기</Link>
Home.js의 전체 구성
import React, {useState} from 'react';
import {Link} from 'react-router-dom';
import {gql, useQuery} from '@apollo/client';
import styled from 'styled-components';
const dataContext = React.createContext();
const Container = styled.div`
`
const Title = styled.h1`
padding: 1%;
align-items: center;
`
const UserInformation = styled.div`
display: flex;
`
function Home() {
const [userID, setUserID] = useState('');
const [userPW, setUserPW] = useState('');
const updateUserID = e => {
const {target : {value}} = e;
//value 변수 자체는 문자 하나하나
//각각 입력될때마다 반응
setUserID(value);
//이 입력되는 값들에 대해
//상태관리화하면 (누적된) 상태관리가 가능해진다.
console.log(userID);
};
const updateUserPW = e => {
const {target : {value}} = e;
//value 변수 자체는 문자 하나하나
//각각 입력될때마다 반응
setUserPW(value);
//이 입력되는 값들에 대해
//상태관리화하면 (누적된) 상태관리가 가능해진다.
console.log(userPW);
};
const saveStateValues = (userID, userPW) => {
localStorage.setItem(userID, userPW);
};
return(
<Container>
<Title>사용자 로그인</Title>
<UserInformation>
<input type='text' placeholder="ID" value={userID} onChange={updateUserID}/>
<input type='password' placeholder="PW" value={userPW} onChange={updateUserPW}/>
</UserInformation>
<Link to={{
pathname: `/${userID}`
}} onClick={() => saveStateValues(userID, userPW)}>로그인하기</Link>
</Container>
)
};
export default Home;
이벤트를 구성하는 경우 작성형태에 유의한다.
- onClick = {()=>function()} → event 인자와 같이 전달
- onClick = {function()} → event 인자를 같이 전달하지 않는다.
4-3. Detail.js - 화면 전환 이후 data를 전달받고 data 유지 및 load
data 저장소 및 hooks(useParams 등)을 통해 이전 component에서 data를 전달받는다.
- 사용자ID는 URL(useParams)를 통해 전달받는다.
- 사용자PW는 localStorage를 통해 전달받는다.
- 기본적으로 data를 local file system으로 입력받고 이에 대한 실시간 감지를 하기 위해 상태관리한다(useState, 최종적으로 받은 text/image data에 대한).
- 상태변수를 return 값에 활용하면 즉시적인 data 반영이 가능해진다.
const {userID} = useParams();
const userPW = localStorage.getItem(userID);
//const userIDByLocal = localStorage.key(userPW);
const [finalText, setFinalText] = useState('');
const [finalImage, setFinalImage] = useState('');
let txtDATA = localStorage.getItem(`${userID}fortxt`);
let imageDATA = localStorage.getItem(`${userID}forimg`);
setFinalText(text);
setFinalImage(fileRead.result);
{finalText? (<pre className="textArea" contentEditable>{finalText}</pre>) : (<div>NO SAVED TEXT DATA</div>)}
{finalImage? (<div className="imageAreaCover"><img className="imageArea" src={finalImage}></img></div>) : (<div>NO SAVED IMAGE DATA</div>)}
※ file system(외부 입출력)을 통해 data를 전달받는 과정에서 상태관리를 바로 적용하지는 않는다.
※ 최종적으로 text/image file을 입력받은 data에 대해 상태관리변수에 담고, 이를 return(화면구현)에 사용한다.
Detail.js의 전체 구성
import React, {useState} from 'react';
import { useParams } from 'react-router';
import styled from 'styled-components'
//import {useRef} from 'react-router-dom';
let fileRead = new FileReader();
const Container = styled.div`
`
function Detail(){
const {userID} = useParams();
const userPW = localStorage.getItem(userID);
//const userIDByLocal = localStorage.key(userPW);
const [finalText, setFinalText] = useState('');
const [finalImage, setFinalImage] = useState('');
let txtDATA = localStorage.getItem(`${userID}fortxt`);
let imageDATA = localStorage.getItem(`${userID}forimg`);
let fileBuffer = null;
async function fileOpenButton(){
[fileBuffer] = await window.showOpenFilePicker();
let fileData = await fileBuffer.getFile();
console.log(fileData);
if(fileData.type !== 'image/png'){
//interface file data
//await fileRead.readAsDataURL(fileData)
let text = await fileData.text();
localStorage.setItem(`${userID}fortxt`, text)
setFinalText(text);
return ;
}else if(fileData.type == 'image/png' || 'image/jpeg'){
//fileReader가 fileData를 먼저 읽어야 한다.
await fileRead.readAsDataURL(fileData);
fileRead.addEventListener('load', () => {
localStorage.setItem(`${userID}forimg` , fileRead.result);
setFinalImage(fileRead.result);
//console.log(fileRead.result);
//console.log(imageArea.src);
})
return;
//fileRead - null, fileRead.result - image URL.
//upload event를 부여할 경우에만 fileRead에서 data를 읽어올 수 있다.
}else{
return;
}
};
return(
<Container>
<button className="fileOpen" type="file" onClick={fileOpenButton}>파일 불러오기</button>
{finalText? (<pre className="textArea" contentEditable>{finalText}</pre>) : (
<div>NO SAVED TEXT DATA</div>)}
{finalImage? (<div className="imageAreaCover"><img className="imageArea" src={finalImage}></img></div>) : (
<div>NO SAVED IMAGE DATA</div>)}
<button className="fileSave">파일 저장하기</button>
<button className="fileSaveAs">다른 이름으로 파일 저장하기</button>
</Container>
)
}
export default Detail;
4-4. 참고
별도의 화면 랜더링이 필요할 경우, 이에 대한 Component를 구성하고 분기처리를 통해 return(화면구현) 한다.
5. 참조링크
React event 처리하기
https://ko.reactjs.org/docs/handling-events.html
Author And Source
이 문제에 관하여([WebDevCurriculum] React 기반의 file system 구현 - txt/image 불러오기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gyrbs22/WebDevCurriculum-React-기반의-file-system-구현저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)