심화 주특기 3강!
- 파이어스토어로 데이터를 관리한다.
- 파이어베이스의 스토리지 서비스를 사용하여 이미지 업로드 기능을 만든다.
- 파일 업로드 전 이미지 미리보기를 하려면 어떻게 하는 지 알아본다.
- 잦은 이벤트 처리 기법에 대해 알아본다.
여러가지 잔기술...
reduce 쓰는 법
let _post = doc.data();
let post = Object.keys(_post).reduce(
(acc, cur) => {
if (cur.indexOf("user_") !== -1) {
return {
...acc,
user_info: { ...acc.user_info, [cur]: _post[cur] },
};
}
return { ...acc, [cur]: _post[cur] };
},
{ id: doc.id, user_info: {} }
);
딕셔너리를 한번에 props 넘기는 법
return <Post key={p.id} {...p}></Post>;
특이한 딕셔너리 할당법 (위와 반대 상황)
const user_info = {
user_name: _user.user_name,
user_id: _user.uid,
user_profile: _user.user_profile,
};
PostDB.add({ ...user_info, ..._post })
.then((doc) => {
let post = { user_info, ..._post, id: doc.id };
dispatch(addPost(post));
history.replace("/");
})
.catch((err) => {
console.log("post 작성에 실패했습니다", err);
});
FileReader() 쓰는 법
const fileInput = React.useRef();
const selectFile = (e) => {
const reader = new FileReader();
const file = fileInput.current.files[0];
reader.readAsDataURL(file);
reader.onloadend = () => {
dispatch(imageActions.setPreview(reader.result));
};
};
return (
<React.Fragment>
<input
type="file"
onChange={selectFile}
ref={fileInput}
/>
</React.Fragment>
);
이미지와 게시글을 같은 버튼(같은 actioncreator) 올리는법
const _image = getState().image.preview;
const _upload = storage.ref(
`images/${user_info.user_id}_${new Date().getTime()}`.putString(
_image,
"data_url"
)
);
_upload.then((snapshot) => {
snapshot.ref
.getDownloadURL()
.then((url) => {
return url;
})
.then((url) => {
PostDB.add({ ...user_info, ..._post, image_url: url })
.then((doc) => {
let post = { user_info, ..._post, id: doc.id, image_url: url };
dispatch(addPost(post));
history.replace("/");
})
.catch((err) => {
console.log("post 작성에 실패했습니다", err);
});
});
});
styled components에서 변수 사용하는 법
const ImageDefault = styled.div`
--size: ${(props) => props.size}px;
// css 값을 변수화해서
width: var(--size); // 이렇게 불러서 사용함
height: var(--size);
background-image: url("${(props) => props.src}");
background-size: cover;
`;
이미지 수정하는 법
const editPostFB = (post_id = null, post = {}) => {
return function (dispatch, getState, { history }) {
if (!post_id) {
console.log("게시글 정보가 없어요.");
return;
}
const _image = getState().image.preview;
const _post_idx = getState().post.list.findIndex((p) => p.id === post_id);
const _post = getState().post.list[_post_idx];
const postDB = firestore.collection("image_community");
if (_image === _post.image_url) {
postDB
.doc(post_id)
.update(post)
.then((doc) => {
dispatch(editPost(post_id, { ...post }));
history.replace("/");
});
} else {
const user_id = getState().user.user.uid;
const _upload = storage
.ref(`images/${user_id}_${new Date().getTime()}`)
.putString(_image, "data_url");
_upload.then((snapshot) => {
snapshot.ref
.getDownloadURL()
.then((url) => {
return url;
})
.then((url) => {
postDB
.doc(post_id)
.update({ ...post, image_url: url })
.then((doc) => {
dispatch(editPost(post_id, { ...post, image_url: url }));
history.replace("/");
});
})
.catch((err) => {
window.alert("이미지 업로드에 실패했어요.");
console.log("앗, 이미지 업로드에 문제가 있어요.");
});
});
}
};
};
...
export default handleActions(
{
...
[EDIT_POST]: (state, action) =>
produce(state, (draft) => {
let idx = draft.list.findIndex((p) => p.id === action.payload.post_id);
draft.list[idx] = { ...draft.list[idx], ...action.payload.post };
}),
},
initialState
);