2021/01/24 - [React] - [React] react-router-dom, redux 를 이용한 페이지 이동 - 떽떽대는 개발공부
오늘은 전 글에 이어 게시판을 만들어볼 것이다.
전 글에서 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 |
댓글