Router
route 기본
export default function MainApp(){
return(
<BrowserRouter>
<Routes>
<Route path="/" element={ <HelloReact/> }/>
<Route path="/card" element={ <Card/> }/>
<Route path="/contact" element={ <ContactApp/> }/>
<Route path="/person" element={ <PersonApp/> }/>
<Route path="/todo" element={ <ComplexReducerHook/> }/>
</Routes>
</BrowserRouter>
)
}

실습
-----------------------------------------------------------------------------------------------MainApp.js
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
import BoardList, { Detail, Write } from "../components/board/BoardList";
import { useState } from "react";
import "./MainApp.css"
import ComplexReducerHook from "../components/hooks/ComplexReducerHook";
import HelloReact from "../components/hello/HelloReact";
export default function MainApp(){
const [item, setItem]=useState([])
return(
<BrowserRouter>
<div id="grid">
<div id="header">여기는 Header입니다.</div>
<div id="aside">
<ul>
<li><Link to="/">게시판 </Link></li>
<li><Link to="/todo">Todo </Link></li>
<li><Link to="/hello">HelloReact </Link></li>
</ul>
</div>
<div>
<Routes>
<Route path="/" element={ <BoardList item={item}/> }/>
<Route path="/write" element={ <Write item={item} setItem={setItem}/> }/>
<Route path="/view/:num" element={ <Detail item={item} setItem={setItem}/> }/>
<Route path="/todo" element={ <ComplexReducerHook/> }/>
<Route path="/hello" element={ <HelloReact/> }/>
</Routes>
</div>
</div>
</BrowserRouter>
)
}
BoardList.js
import { useEffect, useRef, useState } from "react";
import { Link, useNavigate, useParams } from "react-router-dom";
export default function BoardList({item}){
return(
<div>
<table>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
{
item.map((item)=><Row key={item.num}
num={item.num}
title={item.title}
author={item.author}
viewCount={item.viewCount}/>)
}
</tbody>
</table>
<Link to="/write">글쓰기 </Link> {/*페이지를 이동할 수 있는링크 */}
</div>
);
}
function Row({num, title,author,viewCount}){
return(
<tr>
<td>{num}</td>
<td>
<Link to={"/view/" +num}>{title}</Link>
</td>
<td>{author}</td>
<td>{viewCount}</td>
</tr>
)
}
export function Detail({item,setItem}){
// /view/:num의 값을 받아옴.
const {num} = useParams()
//조회수 증가시키기
useEffect(()=>{
const copyItem=[...item]
copyItem.map((each)=> {
if(each.num==num){
each.viewCount+=1
return {...each}
}
return each
})
setItem(copyItem)
},[])
const detailItem = item.filter((each)=>each.num==num)[0] //title을 눌렀을때 상세정보 보기
return(
<div>
<div>
번호:{detailItem.num}
</div>
<div>
제목:{detailItem.title}
</div>
<div>
작성자:{detailItem.author}
</div>
<div>
조회수:{detailItem.viewCount}
</div>
<div>
내용:{detailItem.desc}
</div>
<div>
<Link to="/">목록으로 돌아가기</Link>
</div>
</div>
)
}
export function Write({setItem, item}){
const titleRef=useRef()
const authorRef=useRef()
const descRef=useRef()
const navigate=useNavigate()
function save(){
setItem([...item,{
num:item.length+1,
title:titleRef.current.value,
author:authorRef.current.value,
desc:descRef.current.value,
viewCount:0
}])
navigate("/") //저장버튼을 누른뒤 어디로 이동할지 정해줌
}
return(
<div>
<div>
<input type="text" placeholder="제목" ref={titleRef} />
</div>
<div>
<input type="text" placeholder="작성자" ref={authorRef} />
</div>
<div>
<textarea placeholder="내용" ref={descRef}></textarea>
</div>
<div>
<button onClick={save}>저장</button>
<Link to="/">목록으로 돌아가기</Link>
</div>
</div>
)
}
------------------------------------------------------------------------------------------------MainApp.js
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
import BoardList, { Detail, Write } from "../components/board/BoardList";
import { useState } from "react";
import "./MainApp.css"
import ComplexReducerHook from "../components/hooks/ComplexReducerHook";
import HelloReact from "../components/hello/HelloReact";
export default function MainApp(){
const [item, setItem]=useState([])
return(
<BrowserRouter>
<div id="grid">
<div id="header">여기는 Header입니다.</div>
<div id="aside">
<ul>
<li><Link to="/articles">게시판 </Link></li>
<li><Link to="/todo">Todo </Link></li>
<li><Link to="/hello">HelloReact </Link></li>
</ul>
</div>
<div>
<Routes>
<Route path="/articles/*" element={ <BoardList item={item}/> }>
<Route path=":num" element={ <Detail item={item} setItem={setItem}/> }/>
</Route>
<Route path="/articles/write" element={ <Write item={item} setItem={setItem}/> }/>
<Route path="/todo" element={ <ComplexReducerHook/> }/>
<Route path="/hello" element={ <HelloReact/> }/>
</Routes>
</div>
</div>
</BrowserRouter>
)
}
----------------------------------------------------------------------------------------------------------------BoardList.js
import { useEffect, useRef, useState } from "react";
import { Link, Outlet, useNavigate, useParams } from "react-router-dom";
export default function BoardList({item}){
return(
<div>
<table>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
{
item.map((item)=><Row key={item.num}
num={item.num}
title={item.title}
author={item.author}
viewCount={item.viewCount}/>)
}
</tbody>
</table>
<Link to="/articles/write">글쓰기 </Link> {/*페이지를 이동할 수 있는링크 */}
{/*Detail Componet (Route 내부의 Route Component) */}
<Outlet/>
</div>
);
}
function Row({num, title,author,viewCount}){
return(
<tr>
<td>{num}</td>
<td>
<Link to={"/articles/" +num}>{title}</Link>
</td>
<td>{author}</td>
<td>{viewCount}</td>
</tr>
)
}
export function Detail({item,setItem}){
// /view/:num의 값을 받아옴.
const {num} = useParams()
//조회수 증가시키기
useEffect(()=>{
const copyItem=[...item]
copyItem.map((each)=> {
if(each.num==num){
each.viewCount+=1
return {...each}
}
return each
})
setItem(copyItem)
},[])
const detailItem = item.filter((each)=>each.num==num)[0] //title을 눌렀을때 상세정보 보기
return(
<div>
<div>
번호:{detailItem.num}
</div>
<div>
제목:{detailItem.title}
</div>
<div>
작성자:{detailItem.author}
</div>
<div>
조회수:{detailItem.viewCount}
</div>
<div>
내용:{detailItem.desc}
</div>
<div>
<Link to="/articles">목록으로 돌아가기</Link>
</div>
</div>
)
}
export function Write({setItem, item}){
const titleRef=useRef()
const authorRef=useRef()
const descRef=useRef()
const navigate=useNavigate()
function save(){
setItem([...item,{
num:item.length+1,
title:titleRef.current.value,
author:authorRef.current.value,
desc:descRef.current.value,
viewCount:0
}])
navigate("/articles") //저장버튼을 누른뒤 어디로 이동할지 정해줌
}
return(
<div>
<div>
<input type="text" placeholder="제목" ref={titleRef} />
</div>
<div>
<input type="text" placeholder="작성자" ref={authorRef} />
</div>
<div>
<textarea placeholder="내용" ref={descRef}></textarea>
</div>
<div>
<button onClick={save}>저장</button>
<Link to="/">목록으로 돌아가기</Link>
</div>
</div>
)
}


게시판을 Redux로 바꾸기
------------------------------------------------------------------------------------------------- BoardSlice.js
import { createSlice } from "@reduxjs/toolkit";
export const BoardSlice=createSlice({
name:"boardSlice",
initialState:[],
reducers:{
regist(state, action){
state.push(action.payload)
},
read(state,action){
state.forEach((board)=>{
if(board.num===parseInt(action.payload)){
board.viewCount+=1
}
})
}
}
})
-------------------------------------------------------------------------------------------------- TodoSlice.js
import { createSlice } from "@reduxjs/toolkit";
export const TodoSlice=createSlice({
name:"todoSlice",
initialState:{
count:0,
todos:[],
completeTodoCount:0
},
reducers:{
addItem(state,action){
state.count+=1
state.todos.push({
id:Date.now(),
item: action.payload.item,
isComplete:false
})
state.completeTodoCount = state.todos
.filter(todo=>todo.isComplete)
.length
},
deleteItem(state,action){
state.count -=1
state.todos=state.todos.filter(todo => todo.id!=action.payload)
state.completeTodoCount = state.todos
.filter(todo=>todo.isComplete)
.length
},
complete(state,action){
state.todos = state.todos.map(todo=>{
if(todo.id === action.payload){
return {...todo, isComplete: !todo.isComplete}
}
return todo
})
state.completeTodoCount = state.todos
.filter(todo=>todo.isComplete)
.length
}
}
})
------------------------------------------------------------------------------------------------------------------ToolkitStore.js
import { configureStore } from "@reduxjs/toolkit";
import { BoardSlice } from "./BoardSlice";
import { TodoSlice } from "./TodoSlice";
export const ToolkitStore = configureStore({
reducer:{
board:BoardSlice.reducer,
todo:TodoSlice.reducer,
}
})
-------------------------------------------------------------------------------------------------------------------MainApp.js
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
import BoardList, { Detail, Write } from "../components/board/BoardList";
import "./MainApp.css"
import ComplexReducerHook from "../components/hooks/ComplexReducerHook";
import HelloReact from "../components/hello/HelloReact";
import { Provider } from "react-redux";
// import ReduxStore from "../store/redux/ReduxStore";
import { ToolkitStore } from "../store/toolkit/ToolkitStore";
export default function MainApp(){
// const reduxStore=ReduxStore()()
return(
<Provider store={ToolkitStore}>
<BrowserRouter>
<div id="grid">
<div id="header">여기는 Header입니다.</div>
<div id="aside">
<ul>
<li><Link to="/articles">게시판 </Link></li>
<li><Link to="/todo">Todo </Link></li>
<li><Link to="/hello">HelloReact </Link></li>
</ul>
</div>
<div>
<Routes>
<Route path="/articles/*" element={ <BoardList /> }>
<Route path=":num" element={ <Detail/> }/>
</Route>
<Route path="/articles/write" element={ <Write /> }/>
<Route path="/todo" element={ <ComplexReducerHook/> }/>
<Route path="/hello" element={ <HelloReact/> }/>
</Routes>
</div>
</div>
</BrowserRouter>
</Provider>
)
}