反応深化班3週目-1
22.04.19(火)
スパルタ符号化クラブ反応深化班-第2週過程-2
作成モジュール rootreducer(Storeconfig設定) に追加投稿 FirebaseコンソールでFirebase Storeを有効にし、一時データ を配置します. firebase.Firestoreをjsに追加する Firestoreからデータ をインポートする. userEffectによるgetPostFB の実行ログイン後のみ/writeにアクセス UserSeletor stateを使用します.user.is login値 is login値がfalseの場合、他のページの が表示されます.(+)ボタンを押すとhistory.push("/write") による投稿の送信(inputbox値をcontentsにインポート) Firestoreにデータを入れる 分インストール(現在の日付、時間が使いやすい) Firestoreに格納されている関数を作成/正常に保存すると、reduxにデータが格納されます. で画像をアップロードする場合、 が使用されます. Storgeに接続し、Firebaseコンソール規則 を設定します.
スパルタ符号化クラブ反応深化班-第2週過程-2
◇記事リストのインポート
作成
// 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}
// 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>
)
...
◇Fire Storeのバインド
// shared/firebase.js
import "firebase/firestore";
...
const firestore = firebase.firestore();
...
export{auth, apiKey, 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함
});
};
};
...
// PostList.js
// 최초 로딩시에 실행
React.useEffect(() => {
dispatch(postActions.getPostFB());
}, []);
◇文章を書く
const [contents, setContents] = React.useState('');
...
const changeContents = (e) => {
setContents(e.target.value);
}
...
<Grid padding="16px">
<Input _onChange={changeContents} label="게시글 내용" placeholder="게시글 작성" multiLine />
</Grid>
yarn add moment
// 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
// 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;
}
}
}
Reference
この問題について(反応深化班3週目-1), 我々は、より多くの情報をここで見つけました https://velog.io/@gwichanlee/리액트-심화반-3주차-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol