리액트 심화반 3주차 - 1
22.04.19(화)
스파르타코딩클럽 리액트 심화반 - 2주차 과정 - 2
◎ 포스트 목록 가져오기
- module 만들기
// src > redux > modules > post.js
// import
import { createAction, handleActions } from "redux-actions"; // Action Creater를 쉽게 만들어줌
import { produce } from "immer"; // 불변성 관련 library
import { firestore } from "../../shared/firebase";
import moment from "moment"
// action
const SET_POST = "SET_POST";
const ADD_POST = "ADD_POST";
// action creators / Using redux-actions
const setPost = createAction(SET_POST, (post_list) => ({post_list}))
const addPost = createAction(ADD_POST, (post) => ({post}))
// initialState
const initialState = {
list: [],
}
const initialPost = {
image_url: "https://velog.velcdn.com/images%2Fgwichanlee%2Fpost%2F5cc3bbe0-550a-4cb7-8804-467f420f6002%2Ftest2.jpg",
contents: "",
comment_cnt: "0",
insert_dt: moment().format("YYYY-MM-DD hh:mm:ss"),
};
// reducer Using redux-actions, immer
export default handleActions(
{
[SET_POST]: (state, action) => produce(state, (draft) => {
draft.list = action.payload.post_list
}),
[ADD_POST]: (state, action) => produce(state, (draft) => {
draft.list.unshift(action.payload.post);
}),
}, initialState
);
// export
const actionCreators={
setPost,
addPost,
getPostFB,
addPostFB,
}
export {actionCreators}
- rootreducer에 추가 (Storeconfig 설정)
// redux/configureStore.js
...
import Post from "./modules/post";
...
const rootReducer = combineReducers({
user: User,
post: Post,
router: connectRouter(history),
});
...
- 게시글 연동하기
// pages/PostList.js
...
import {useSelector} from "react-redux";
import Post from "../components/Post";
...
const PostList = (props) => {
const post_list = useSelector((state) => state.post.list);
...
return (
<React.Fragment>
{post_list.map((p, idx) => {
return <Post key={p.id} {...p}/>
})}
</React.Fragment>
)
...
◎ 파이어스토어 연동하기
- Firebase Console에서 Firebase Store 활성화 및 임시 데이터 넣어놓기
- firebase.js 에 Firestore 추가
// shared/firebase.js
import "firebase/firestore";
...
const firestore = firebase.firestore();
...
export{auth, apiKey, firestore};
- firestore에서 데이터 가져오기
//redux/modules/post.js
import { firestore } from "../../shared/firebase";
...
const getPostFB = () => {
return function (dispatch, getState, { history }) {
const postDB = firestore.collection("post"); // firestore.collection 가져오기, "post": collection 이름
postDB.get().then((docs) => {
let post_list = [];
// 반복문 사용
docs.forEach((doc) => {
// console.log(doc.id, doc.data()); // 데이터 형태 확인
let _post = doc.data(); // 데이터 내용 가져오기
// 데이터 모양 수정
let post = {
id: doc.id,
user_info: {
user_name: _post.user_name,
user_profile: _post.user_profile,
user_id: _post.user_id,
},
contents: _post.contents,
image_url: _post.image_url,
comment_cnt: _post.comment_cnt,
imsert_dt: _post.insert_dt
}
post_list.push(post);
});
// 리스트 확인하기!
console.log(post_list);
dispatch(setPost(post_list)); // Action을 Dispatch함
});
};
};
...
- useEffect를 통해, getpostFB 실행
// PostList.js
// 최초 로딩시에 실행
React.useEffect(() => {
dispatch(postActions.getPostFB());
}, []);
◎ 포스트 작성하기
- 로그인 후에만 /write에 접근하게 하기
- useSeletor를 이용해 state.user.is_login 값을 가져옴
- is_login 값이 false 일때, 다른 페이지를 보여줌
- (+) 버튼 누를 때, history.push("/write")
- 작성한 게시글 내용 넘겨주기 (contents에 inputbox값 가져오기)
const [contents, setContents] = React.useState('');
...
const changeContents = (e) => {
setContents(e.target.value);
}
...
<Grid padding="16px">
<Input _onChange={changeContents} label="게시글 내용" placeholder="게시글 작성" multiLine />
</Grid>
- firestore에 데이터 넣기
- moment 설치 (현재 날짜, 시간을 쉽게 사용할 수 있음)
yarn add moment
- firestore에 저장하는 함수 만듦 / 성공시, redux에 데이터를 넣음.
// redux/modules/post.js import moment from "moment"; ... const initialPost = { image_url: "기본 이미지 url", contents: "", comment_cnt: 0, insert_dt: moment().format("YYYY-MM-DD hh:mm:ss"), }; ... const addPostFB = (contents = "") => { return function (dispatch, getState, { history }) { // DB를 설정 const postDB = firestore.collection("post"); // user 정보를 state에서 가져옴 const _user = getState().user.user; const user_info = { user_name: _user.user_name, user_id: _user.uid, user_profile: _user.user_profile, }; // 저장할 정보 구성 const _post = { ...initialPost, contents: contents, insert_dt: moment().format("YYYY-MM-DD hh:mm:ss") }; // 잘 만들어졌나 확인 // console.log(_post); // DB에 내용 저장 postDB.add({...user_info, ..._post}).then((doc) => { // 아이디를 추가 let post = {user_info, ..._post, id: doc.id}; // redux에 넣어줌 dispatch(addPost(post)); // 페이지 이동 / replace: 뒤로가기시, 원래 페이지로 안감 history.replace("/") }).catch((err) => { console.log('post 작성 실패!', err); }); }; }; ... [ADD_POST]: (state, action) => produce(state, (draft) => { // unshift: 배열 맨 앞에 데이터를 넣어줌 draft.list.unshift(action.payload.post); }),
◎ firebase Storage
- 이미지 업로드시, 이용할 예정
- Storge 연결하기 및 Firebase Console Rules 세팅
// shared/firebase.js
...
import "firebase/firestore";
import "firebase/storage";
...
const apiKey = firebaseConfig.apiKey;
const auth = firebase.auth();
const firestore = firebase.firestore();
const storage = firebase.storage();
export{auth, apiKey, firestore, storage};
// 파이어베이스 콘솔 -> Storage에서 규칙(rules) 탭으로 이동!아래처럼 바꿔주기!
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Author And Source
이 문제에 관하여(리액트 심화반 3주차 - 1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gwichanlee/리액트-심화반-3주차-1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)