React Hooks
// setName을 이용해서 state를 업데이트 가능 // 아래와 같은 방식으로 사용 const [name, setName] = useState("")
State VS Props
Props는 변경 불가능(immutable)
데이터를 변하게 하려면 부모 컴포넌에서 state를 변경 ⇒ 자식 컴포넌트도 변경
// Props의 구성요소로 todoData, setTodoData, ...를 부모 컴포넌트에서 가져옴 // 화살표함수의 형태로 선언 const Lists = React.memo(({ todoData, setTodoData, handleClick }) => { // ... } // export deafult Lists를 해서 Lists함수를 import로 부를 수 있게 설정 export default Lists // 혹은 한번에 선언, 기본함수의 형태로 선언 export default function Lists({ todoData, setTodoData, handleClick }) { // ... }
컴포넌트화 (개인적인 의견)
TailWindCSS
npm install -D tailwindcss postcss autoprefixer
/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./src/**/*.{js,jsx,ts,tsx}" ], theme: { extend: {}, }, plugins: [], }
@tailwind base; @tailwind components; @tailwind utilities;
장점
단점 (개인적)
사용 방법
<div className="flex items-center justify-center w-screen h-screen bg-blue-100"> <div className="w-full p-6 m-4 bg-white rounded shadow lg:w-3/4 lg:max-w-lg"> <div className="flex justify-between mb-3">
Drag and Drop
npm install react-beautiful-dnd --save
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd' // DragDropContext : Drag and Drop을 활성화해야하는 부분을 감싸기 // Droppable : Drop 가능한 영역을 감싸기, <Draggable /> 포함 // Draggable : Drag 가능한 영역을 감싸기 // 아래와 같이 보통 DragDropContext 내부에 Droppable 내부에 Draggable 존재 <DragDropContext onDragEnd={handleEnd}> <Droppable droppableId="todo"> {(provided) => ( <div {...provided.droppableProps} ref={provided.innerRef}> {todoData.map((data, index) => ( <Draggable key={data.id} draggableId={data.id.toString()} index={index}> ....
<Droppable droppableId="todo"> {(provided) => ( // provided가 전체를 감쌈 // droppable인 경우 div에 {...provided.droppableProps} ref={provided.innerRef}를 설정 <div {...provided.droppableProps} ref={provided.innerRef}> {todoData.map((data, index) => ( // map이기 때문에 key값 필요 <Draggable key={data.id} draggableId={data.id.toString()} index={index}> {(provided, snapshot) => ( // provided와 snapshot이 전체를 감쌈 // draggable인 경우 div에 key={id} {...provided.draggableProps} // ref={provided.innerRef} {...provided.dragHandleProps} 값이 필요 // Props로 List.js에 아래에 해당하는 값을 넘겨줌 <List handleClick={handleClick} key={data.id} id={data.id} title={data.title} completed={data.completed} todoData={todoData} setTodoData={setTodoData} provided={provided} snapshot={snapshot} /> )} </Draggable> ))} {provided.placeholder} </div> )} </Droppable> // provided.placeholder를 사용하면 드래그가 자연스러워짐
// <DragDropContext onDragEnd={handleEnd}> 에서 handleEnd를 사용 const handleEnd = (result) => { console.log(result) if (!result.destination) return; const newTodoData = [...todoData]; // 변경시키는 아이템을 배열에서 지워주기 // return 값으로 지워진 아이템을 잡아주기 const [reorderedItem] = newTodoData.splice(result.source.index, 1); // 원하는 자리에 reorderedItem을 insert 하기 newTodoData.splice(result.destination.index, 0, reorderedItem); setTodoData(newTodoData); localStorage.setItem('todoData', JSON.stringify(newTodoData)); }
리액트 불변성 지키기
React.memo
// 사용방법 : 원하는 컴포넌트를 React.memo로 감싸기 // 화살표함수에서 사용가능 const Lists = React.memo(({ todoData, setTodoData, handleClick }) => { // ... }
useCallback
// 사용 방법 : useCallback 안에 콜백함수와 의존성 배열을 순서대로 넣기 // 함수 내에서 참조하는 state, props가 있다면 의존성 배열에 추가 ex) [todoData] const handleClick = useCallback((id) => { let newTodoData = todoData.filter(data => data.id !== id) console.log('newTodoData', newTodoData) setTodoData(newTodoData) localStorage.setItem('todoData', JSON.stringify(newTodoData)); }, [todoData] ); // useCallback으로 인해 todoData값이 변하지 않으면 함수가 재생성되지 않음
useMemo
// 사용방법 : useMemo로 감싸고 의존성 배열에 감싸진 함수에서 사용하는 값을 넣기 function Component({a, b}) { const result = useMemo(() => compute(a, b), [a, b]) return <div>{result}</div> }
React Developer Tools
localStorage에 값 담기
const handleClick = useCallback((id) => { let newTodoData = todoData.filter(data => data.id !== id) console.log('newTodoData', newTodoData) setTodoData(newTodoData) // setTodoData로 newTodoData를 설정했을때 localStorage에도 저장 // 객체나 배열을 저장시에는 JSON.stringify를 이용해서 저장 localStorage.setItem('todoData', JSON.stringify(newTodoData)); }, [todoData]
// 값이 존재하면 값을 가져오고 값이 존재하지 않으면 값을 가져오지 않음 const initialTodoData = localStorage.getItem("todoData") ? JSON.parse(localStorage.getItem("todoData")) : []; // 반환된 값을 사용 const [todoData, setTodoData] = useState(initialTodoData)