* 기본 이미지 출처
https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png
▶ 정말 어려웠다;
▶ 처음에는 이미지를 올리면 올리려는 이미지가 보이고 최종 이미지를 업로드하는 것이었는데
이 과정에서 문제가 계속 있었다
▶ (결론) 이미지를 올리면 user 정보(me)에 이미지가 저장되고 화면에 로딩되는 것
useEffect(() => {
dispatch(loadMyInfoRequest());
}, [imagePaths]);
//imagePaths 값이 변경될 때마다(프로필 이미지 변경될 때 마다 load됨)
import React, { useEffect } from "react";
import Profile from "../components/Profile";
import { loadPostsRequest } from "../redux/feature/postSlice";
import { loadMyInfoRequest } from "../redux/feature/userSlice";
import { loadWordsRequest } from "../redux/feature/wordSlice";
const profile = () => {
const dispatch = useDispatch();
const { me } = useSelector((state) => state.user);
const { mainPosts } = useSelector((state) => state.post);
const { wordLists } = useSelector((state) => state.word);
const id = useSelector((state) => state.user.me?.id);
const { imagePaths } = useSelector((state) => state.user);
const postResult = mainPosts.filter((post) => post.UserId === id);
const wordResult = wordLists.filter((word) => word.UserId === id);
useEffect(() => {
dispatch(loadPostsRequest());
dispatch(loadWordsRequest());
}, []);
useEffect(() => {
dispatch(loadMyInfoRequest());
}, [imagePaths]); //이 부분이 핵심(이미지가 변경될 때 load 다시 실행)
return (
<>
<NavbarForm me={me}>
{me ? (
<Profile me={me} postResult={postResult} wordResult={wordResult} />
) : (
<LoginForm />
)}
</NavbarForm>
</>
);
};
export default profile;
const Profile = ({ me, postResult, wordResult }) => {
const imageInput = useRef();
const onClickImageUpload = useCallback(() => {
imageInput.current.click();
}, [imageInput.current]);
const onChangeImages = useCallback((e) => {
console.log("images", e.target.files);
const imageFormData = new FormData();
[].forEach.call(e.target.files, (f) => {
imageFormData.append("image", f);
});
dispatch(uploadProfileImageRequest(imageFormData));
}, []);
return (
<div className="flex">
<form encType="multipart/form-data">
<input
type="file"
name="image"
multiple
hidden
ref={imageInput}
onChange={onChangeImages}
/>
<div className="flex">
<button
type="button"
className="bg-gray-100 rounded-full w-28 h-5 relative left-32 bottom-10 cursor-pointer "
onClick={onClickImageUpload}
>
<p className="font-bold">프로필 변경</p>
</button>
</div>
</form>
{me.profileImg === "" ? (
<img
alt="profile-img"
src="https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png" //초기값
className="rounded-full h-40 w-40"
/>
) : (
<img
className="rounded-full h-40 w-40"
src={`http://localhost:3005/profile/${me.profileImg}`} //변경된 이미지
alt={me.profileImg}
/>
)}
)
}
export default Profile
function uploadProfileImageAPI(data) {
return axios.post("/user/image", data);
}
function* uploadProfileImage(action) {
try {
const data = action.payload;
const result = yield call(uploadProfileImageAPI, data);
yield put(uploadProfileImageSuccess(result.data));
} catch (error) {
yield put(uploadProfileImageFailure(error));
console.log(error);
}
}
uploadProfileImageSuccess: (state, action) => {
const data = action.payload;
state.imagePaths = data;
state.uploadProfileImageLoading = false;
state.uploadProfileImageComplete = true;
},
▶ model에 user 정보에 이미지 넣을 곳 필요(본인은 string타입, profileImg로 지정)
const fs = require("fs");
const path = require("path");
const { User } = require("../models");
const { isLoggedIn, isNotLoggedIn } = require("./middlewares");
const router = express.Router();
try {
fs.accessSync("uploads/profile");
} catch (error) {
console.log("uploads/profile 폴더가 없으므로 새로 생성합니다.");
fs.mkdirSync("uploads/profile");
}
//프로필 이미지
const upload = multer({
storage: multer.diskStorage({
destination(req, file, done) {
done(null, "uploads/profile");
},
filename(req, file, done) {
//파일이미지.png
const ext = path.extname(file.originalname); //확장자 추출(.png)
const basename = path.basename(file.originalname, ext); //파일이미지
done(null, basename + "_" + new Date().getTime() + ext); //파일이미지1234849.png
},
}),
limits: { fileSize: 20 * 1024 * 1024 }, // 20MB
});
router.post(
"/image",
isLoggedIn,
upload.single("image"), //하나의 이미지만 필요
async (req, res, next) => {
await User.update(
{ profileImg: req.file.filename },
{ where: { id: req.user.id } }
);
res.json(req.file);
}
);