Router, Redux

GW·2023년 9월 15일

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

  • App 에서 Component4, Component5, Component5 로 LoginData State 를 전달하려면 ..
  • State 를 모두 전달해야만 한다 . 만약 컴포넌트가 수십개라면??
  • 같은 상황을 Redux 로 사용한다면
  • State 를 전달하기 위한 복잡한 과정이 사라진다

게시판을 Redux로 바꾸기

Redux Toolkit

------------------------------------------------------------------------------------------------- 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>
    )
}

0개의 댓글