2021/01/24 - [React] - [React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부
[React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부
오늘은 그동안 공부했던 것을 바탕으로 react-router-dom 과 redux 를 이용한 페이지 구현하는 부분을 포스팅 해보겠다. 원레는 게시판을 만들어보려고 했는데 오늘은 이 부분 구현하는 데 시간을 많
ddeck.tistory.com
오늘은 전 글에 이어 게시판을 만들어볼 것이다.
전 글에서 ui 는 거의 다 작성해 두었고, 오늘은 boardReducer를 만들고, 글을 등록해서 store 에 저장하면
store를 구독하고 있는 list 에서 게시글 목록을 받아오는 부분을 할 것이다.
src/modules/boardReducer.js
const _SAVE = 'DATA_SAVE'; export const dataSave = (inputData) => ({ type: _SAVE, inputData: { id: inputData.id, title: inputData.title, content: inputData.content } }) const initialState = { lastId: 0, inputData: [ { id: '', title: '', content: '' } ] } export default function boardReducer(state = initialState, action){ switch(action.type) { case _SAVE: console.log(state.inputData) return { lastId: state.lastId + 1, inputData: state.inputData.concat({ ...action.inputData, id: state.lastId + 1, }) } default: return state } }
먼저, 타입을 지정 해주고 글 작성시 호출될 datasave 함수를 작성하였다.
글 작성 페이지에서 submit 버튼을 클릭하게 되면 datasave 함수에 dispatch 하여 저장된 데이터를 받아오고, export default 설정된 boardReducer 에서 action 으로 받아온 데이터를 전달 받을 수 있다.
중요한 점은 리듀서에서는 순수 함수만을 사용해야 함으로 state의 값을 직접 수정할 수 없다는 것이다.
그래서 나는 concat 함수를 사용하였는데, 이 부분에서 괜히 삽질을 했다ㅠ
concat 함수로 배열을 추가 해주기 위해 initialData에서 대괄호 처리를 해주어야 중괄호로 묶이는 배열들을 계속 concat 처리할 수 있다. 아니면 에러가 발생될 것이다.
src/components/BoardNew.js
import React, { useState } from 'react'; import { useDispatch } from 'react-redux'; import { dataSave } from '@modules/boardReducer'; import { uriSave } from '@modules/uriReducer' import { useHistory } from 'react-router-dom'; function BoardNew() { // title, content 를 제어하기 위해 선언 const [title, setTitle] = useState('') const [content, setContent] = useState('') // 함수형 컴포넌트에서 useDispatch 사용을 위해 선언 const dispatch = useDispatch(); //data dispatch 후 list 페이지로 이동하기 위해 선언 const history = useHistory(); const onSave = () => { // reducer 에 선언된 초기값과 동일한 타입으로 data 값 설정 const _inputData = { id: '', title: title, content: content } // 리듀서의 dataSave 함수에 dispatch dispatch(dataSave(_inputData)) // input 값 reset setTitle('') setContent('') // data dispatch 후 페이지 이동 history.push('/') // 페이지 이동 시 footer 의 button 설정을 위해 dispatch dispatch(uriSave('/')) } // input 값이 onChange 될 때마다 호출되어 setTitle, setContent 에 값을 넣어 제어한다. const handleTitle = (e) => { setTitle(e.target.value) } const handleContent = (e) => { setContent(e.target.value) } return( <div> <h2>글 작성</h2> <div> <div> <input type='text' className='inputTitle' placeholder='제목을 입력하세요' onChange={handleTitle} value={title} /> </div> <div> <textarea className='inputContent' placeholder='내용을 입력하세요' onChange={handleContent} value={content} /> </div> <div> <button type='button' onClick={onSave}>submit</button> </div> </div> </div> ) } export default BoardNew;
BoardNew.js 에서는 먼저 input 란에 value 값이 입력 될 때마다 입력되는 값을 계속 저장을 해야한다.
이를 위해 onChange 로 handleContent로 값을 계속 setContent 에 넣어 주었다.
그리고 함수형 컴포넌트에서 useDispatch 를 사용하기 위해 dispatch 라는 함수를 먼저 선언 해주었다.
글 저장 버튼이 클릭되면 onSave 함수가 호출되고, reducer 에서 초기화한 data 값과 동일한 타입으로 맞춰준다.
먼저 선언한 dispatch 함수를 통해 reducer 에 선언되어 있는 saveData 함수에 넘겨주고 input 란은 reset 해준다.
추가로 submit 버튼 클릭 후 dispatch 후 list 페이지로 이동할 때 새로고침 되면 store 에 저장되어 있는 state 값이 초기화 되기 때문에 useHistory 를 이용하여 페이지 이동하고 uriReducer 의 uriSave 를 호출하여 footer 부분의 버튼이 제대로 동작하도록 한다.
src/components/BoardList.js
import React from 'react'; import { useSelector } from 'react-redux'; function BoardList() { // useSelector 로 boardReducer 에 있는 inputData 값을 가져온다. const {inputData} = useSelector(state => state.boardReducer) // useSelector 로 boardReducer 에 있는 lastId 값을 가져온다. const {lastId} = useSelector(state => state.boardReducer) 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 ? // lastId 가 0이 아닐때만 목록을 보여준다. inputData.map(rowData => ( rowData.id !== '' && // rowData의 id 가 ''이 아닐때 목록을 보여준다. <tr> <td className='listTableIndex'>{rowData.id}</td> <td className='listTableTitle'>{rowData.title}</td> </tr> )) : // 작성된 목록이 없을 때 보여줄 내용 <tr> <td className='listTableIndex'></td> <td className='listTableTitle noData'>작성된 글이 없습니다.</td> </tr> } </tbody> </table> </div> </div> ) } export default BoardList;
boardList.js 에서는 현재 store 의 state 값을 가져오고, 그 값에 따라 어떤 내용을 보여줄 지 정한다.
먼저 useSelector 를 통해 현재 state 를 받아오고, 그 값에 따라 list 를 보일 지, 내용이 없다고 나타낼 지 알려준다.
이제 글 작성에 대한 부분은 완성 되었다.
다음 글은 리스트에서 글 제목을 클릭하면 해당 글로 이동하는 부분을 구현해볼 것이다.

'React' 카테고리의 다른 글
[React] redux를 이용하여 게시판 만들기(3) - 떽떽대는 개발공부 (0) | 2021.01.27 |
---|---|
[React] redux를 이용하여 게시판 만들기(2) - 떽떽대는 개발공부 (0) | 2021.01.26 |
[React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부 (3) | 2021.01.24 |
[React] express 를 이용하여 서버사이드렌더링 - 떽떽대는 개발공부 (0) | 2021.01.23 |
[React] redux 를 이용한 예제 - 떽떽대는 개발공부 (0) | 2021.01.22 |
댓글