React

[React] redux를 이용하여 게시판 만들기(2) - 떽떽대는 개발공부

떽이 2021. 1. 26. 18:17

2021/01/25 - [React] - [React] redux 를 이용하여 게시판 만들기(1) - 떽떽대는 개발공부

 

[React] redux 를 이용하여 게시판 만들기(1) - 떽떽대는 개발공부

2021/01/24 - [React] - [React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부 [React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부 오늘은 그동안 공부했던 것을..

ddeck.tistory.com

 

 

 

오늘은 redux 를 이용하여 게시판 만들기를 이어서 포스팅 하도록 하자.

저번 글에서는 글 작성과 작성된 글을 list 에서 보여주는 부분을 구현했다.

이번 글에서는 작성된 글을 상세보기 페이지에서 확인할 수 있도록 해보자.

먼저 boardContent.js 를 간단히 작성한다.

src/components/BoardContent.js

import React from 'react';

function BoardContent() {
    return(
        <div>
            <h2>상세보기</h2>
            <div>
                <div>
                    <input type='text' />
                </div>
                <div>
                    <textarea />
                </div>
                <div>
                    <button type='button'>edit</button>
                    <button type='button'>delete</button>
                </div>
            </div>
        </div>
    )
}

export default BoardContent;

 

이제, BoardList 에서 목록 클릭 시 해당 글로 이동할 수 있도록 BoardList에 코드를 추가 해준다.

src/components/BoardList.js

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Link } from 'react-router-dom';
import { selectRow } from '@modules/boardReducer'

function BoardList() {
    const {inputData} = useSelector(state => state.boardReducer)
    const {lastId} = useSelector(state => state.boardReducer)

	// 클릭한 글의 id를 넘겨주기 위해 dispatch 를 사용한다.
    const dispatch = useDispatch();

	// reducer 의 selectRow 함수에 선택한 id값을 넘겨준다.
    const selectContent = (id) => {
        dispatch(selectRow(id))
    }

    return(
        <div>
            <h2>게시판</h2>
            <div>
                <table className='listTable'>
                    <tbody>
                        <tr>
                            <td className='listTableIndex th'>index</td>
                            <td className='listTableTitle th'>title</td>
                        </tr>
                        {lastId !== 0 ?
                            inputData.map(rowData => (
                                rowData.id !== '' &&
                                <tr>
                                	// 해당 글을 클릭하면 Link to 로 컴포넌트가 이동되며, td에 onClick 이벤트를 추가하여 id 값을 전달한다.
                                    // 이 때 id 값을 매개변수로 주기 위해 onClick 을 함수형으로 전달 하였다.
                                    <td className='listTableIndex' onClick={() => selectContent(rowData.id)}>
                                        <Link to='/BoardContent'>{rowData.id}</Link>
                                    </td>
                                    <td className='listTableTitle' onClick={() => selectContent(rowData.id)}>
                                        <Link to='/BoardContent'>{rowData.title}</Link>
                                    </td>
                                </tr>
                            )) : 
                            <tr>
                                <td className='listTableIndex'></td>
                                <td className='listTableTitle noData'>작성된 글이 없습니다.</td>
                            </tr>
                        }
                    </tbody>
                </table>
            </div>
        </div>
    )
}

export default BoardList;

 

boardReducer.js 에서 전달 받은 id로 select 할 data를 뽑는다.

역시 순수함수로 작성되어야 하기 때문에 전달받을 data 를 담아줄 selectRowData 를 생성하였다.

src/modules/boardReducer.js

const _SAVE = 'DATA_SAVE';
const _SELECT = 'DATA_SELECT'

export const dataSave = (inputData) => ({
    type: _SAVE,
    inputData: {
        id: inputData.id,
        title: inputData.title,
        content: inputData.content
    }
})

// BoardContent.js 에서 id값을 매개변수로 받는다.
export const selectRow = (id) => ({
    type: _SELECT,
    inputData: {
        id: id,
    }
})

const initialState = {
    lastId: 0,
    inputData: [
        {
            id: '',
            title: '',
            content: ''
        }
    ],
    // select 된 data를 담아주기 위해 생성
    selectRowData: {}
}

export default function boardReducer(state = initialState, action){
    switch(action.type) {
        case _SAVE:
            return {
                lastId: state.lastId + 1,
                inputData: state.inputData.concat({
                    ...action.inputData,
                    id: state.lastId + 1,
                })
            }
        case _SELECT:
            return {
                ...state,
                // state 에 action 으로 전달받은 id값과 일치하는 data가 있다면 return 해준다.
                selectRowData: state.inputData.find(row => row.id === action.inputData.id)
            }
        default:
            return state
    }
}

 

이제 BoardContent.js 에서 선택된 값을 state 에서 받아온다.

src/components/BoardContent.js

import React from 'react';
import { useSelector } from 'react-redux'

function BoardContent() {
    const { selectRowData } = useSelector(state => state.boardReducer)

    return(
        <div>
            <h2>상세보기</h2>
            <div>
                <div>
                    <input type='text' className='inputTitle' value={selectRowData.title} />
                </div>
                <div>
                    <textarea className='inputContent' value={selectRowData.content} />
                </div>
                <div>
                    <button type='button' className='editBtn'>edit</button>
                    <button type='button' className='deleteBtn'>delete</button>
                </div>
            </div>
        </div>
    )
}

export default BoardContent;

 

이렇게 하면 아래와 같이 목록 클릭 시 해당 글을 확인할 수 있다.