2024-04-08 81일차 React

민짱·2024년 4월 8일

📅2024. 04. 08 81일차


🎨 React_TODOLIST

TodoList 구조

최초 구조

NewTodoForm, TodoList로 나뉨

TodoList에서 TodoListItem 분리

OptionDrawer와 EditTodoModal 추가

NoticeSnackbar 추가

상태관리 툴 x, 직접 자식 엘리먼트에 전달

상태관리 툴 o, 필요한 엘리먼트에서 상태를 직접 주입받는다

리코일 적용 전 state를 status로 변경

github

  • 어떤곳은 state고 어떤곳은 status여서 용어가 헷갈릴수 있음
    그리고 state는 useState로 인식하기 위해서 변수명 변경작업

recoil install,recoil import, todosAtom 적용

github

  • recoil 설치 및 import
  • key default 설정
  • RecoilRoot로 감싸기
import { RecoilRoot, atom, selector, useRecoilState, useRecoilValue } from 'recoil';

const todosAtom = atom({
  key: 'app/todosAtom',
  default: [],
});

function useTodosStatus() {
  const [todos, setTodos] = React.useState([]);
  const [todos, setTodos] = useRecoilState(todosAtom);
  // const [todos, setTodos] = React.useState([]);
  
  //생략
  
  //생략
  export default function themeApp() {
  const theme = RootTheme();

  return (
    <RecoilRoot>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <App />
      </ThemeProvider>
    </RecoilRoot>
  );
}

lastTodoIdAtom 적용

github


const lastTodoIdAtom = atom({
  key: 'app/lastTodoIdAtom',
  default: 0,
});

//생략
function useTodosStatus() {
  const [todos, setTodos] = useRecoilState(todosAtom);
  // const [todos, setTodos] = React.useState([]);
  const lastTodoIdRef = React.useRef(0);
  const [lastTodoId, setLastTodoId] = useRecoilState(lastTodoIdAtom);
  const lastTodoIdRef = React.useRef(lastTodoId);
 //생략

newTodoForm 에서 직접 todosStatus를 주입받도록

github

const todosAtom = atom({
  key: 'app/todosAtom',
  default: [],
});

const lastTodoIdAtom = atom({
  key: 'app/lastTodoIdAtom',
  default: 0,
});

function useTodosStatus() {
  const [todos, setTodos] = useRecoilState(todosAtom);
  // const [todos, setTodos] = React.useState([]);
  const [lastTodoId, setLastTodoId] = useRecoilState(lastTodoIdAtom);
  const lastTodoIdRef = React.useRef(lastTodoId);

  lastTodoIdRef.current = lastTodoId;
  
  //생략
  
  function App() {
  const todosStatus = useTodosStatus();
  const noticeSnackbarStatus = useNoticeSnackbarStatus();

  React.useEffect(() => {
    todosStatus.addTodo('스쿼트\n런지');
    todosStatus.addTodo('벤치');
    todosStatus.addTodo('데드');
  }, []);

  return (
    <>
      <AppBar position="fixed">
        <Toolbar>
          <div className="tw-flex-1">
            <FaBars onClick={() => setOpen(true)} className="tw-cursor-pointer" />
          </div>
          <div className="logo-box">
            <a href="/" className="tw-font-bold">
              TODO!
            </a>
          </div>
          <div className="tw-flex-1 tw-flex tw-justify-end">
            <a href="/write">글쓰기</a>
          </div>
        </Toolbar>
      </AppBar>
      <Toolbar />
      <NoticeSnackbar status={noticeSnackbarStatus} />
      <NewTodoForm noticeSnackbarStatus={noticeSnackbarStatus} />
      <TodoList todosStatus={todosStatus} noticeSnackbarStatus={noticeSnackbarStatus} />
    </>
  );
}

const NewTodoForm = ({ noticeSnackbarStatus }) => {
  const todosStatus = useTodosStatus();

TodoList, OptionDrawer, EditModal에서 직접 todosStatus를 주입 받도록

github

  • newTodoForm에서 했듯이 TodoList, OptionDrawer, EditModal에서 todosStatus를 직접 주입받도록 수정

오늘의 개념

recoil-persist?

  • 새로고침해도 데이터가 날아가지 않게 관리해줄 때 사용한다.

localStorage
사용자가 데이터를 지우지 않는 이상, 브라우저나 OS를 종료해도 계속 브라우저에 남아있음 (영구성)
단, 동일한 브라우저를 사용할 때만 해당
지속적으로 필요한 데이터 저장 (자동 로그인 등)
sessionStorage
데이터가 오리진 뿐만 아니라 브라우저 탭에도 종속되기 때문에, 윈도우나 브라우저 탭을 닫을 경우 제거
일시적으로 필요한 데이터 저장 (일회성 로그인 정보, 입력폼 저장 등)

  • localStorage : 로컬에 도메인별로 지속되는 storage (브라우저를 닫아도 사라지지 않음)
  • sessionStorage : 세션이(탭, 브라우저)가 종료될 때까지 지속되는 storage (브라우저를 닫으면 사라짐)

Recoil-persist 설치방법

  • npm install recoil recoil-persist

localStorage에 저장하는 법 (코드펜 이용)


import React, { useState } from "https://cdn.skypack.dev/react@18";
import ReactDOM from "https://cdn.skypack.dev/react-dom@18";
import {
	RecoilRoot,
	atom,
	atomFamily,
	useRecoilState
} from "https://cdn.skypack.dev/recoil";

import { recoilPersist } from "https://cdn.skypack.dev/recoil-persist";
const { persistAtom } = recoilPersist();

const pageNo1Atom = atom({
	key: "app/pageNo1Atom",
	default: 0,
	effects_UNSTABLE : [persistAtom],
});

const pageNoAtomFamily = atomFamily({
	key: "app/pageNoAtomFamily",
	default: (no) => 0
});

function Page1() {
	const [no, setNo] = useRecoilState(pageNo1Atom);

	return (
		<>
			<h3>페이지1</h3>
			<ul>
				<li>페이지 1의 숫자 : {no}</li>
				<li>
					<button onClick={() => setNo(no + 1)}>증가</button>
				</li>
			</ul>
		</>
	);
}

function Page2() {
	const [no, setNo] = useRecoilState(pageNoAtomFamily(2));

	return (
		<>
			<h3>페이지2</h3>
			<ul>
				<li>페이지 2의 숫자 : {no}</li>
				<li>
					<button onClick={() => setNo(no + 1)}>증가</button>
				</li>
			</ul>
		</>
	);
}

function Page3() {
	const [no, setNo] = useRecoilState(pageNoAtomFamily(2));

	return (
		<>
			<h3>페이지3</h3>
			<ul>
				<li>페이지 3의 숫자 : {no}</li>
				<li>
					<button onClick={() => setNo(no + 1)}>증가</button>
				</li>
			</ul>
		</>
	);
}

function Page4() {
	const [no, setNo] = useRecoilState(pageNoAtomFamily(1));

	return (
		<>
			<h3>페이지4(페이지1의 데이터를 공유 받음)</h3>
			<ul>
				<li>페이지 4의 숫자 : {no}</li>
				<li>
					<button onClick={() => setNo(no + 1)}>증가</button>
				</li>
			</ul>
		</>
	);
}

const App = () => {
	const [pageNo, setPageNo] = useState(1);

	const switchPage = () => {
		setPageNo(pageNo + 1 <= 4 ? pageNo + 1 : 1);
	};

	const pageName = "page" + pageNo;

	return (
		<>
			<button onClick={switchPage}>스위치</button>
			{pageName == "page1" && <Page1 />}
			{pageName == "page2" && <Page2 />}
			{pageName == "page3" && <Page3 />}
			{pageName == "page4" && <Page4 />}
		</>
	);
};

function Root() {
	return (
		<RecoilRoot>
			<App />
		</RecoilRoot>
	);
}

안드로이드 연동

ionic capacitor

안드로이드 스튜디어 다운

0개의 댓글