Project : helprogrammers - 소개(초대장)
Invitation ✉️
To. 지옥의 알고리즘을 헤쳐나가는 개발자 여러분!
알고리즘을 풀고 계신가요? 도움이 필요하시다고요?! 그렇다면 여러분을 초대합니다. Helprogrammers에서 여러분의 문제를 해결해보세요!
👇 Helprogrammers 바로가기!
From. 당신을 도와줄 Helprogrammers
프로젝트 소개
Concept
💡 어려운 알고리즘 문제를 공유하고 함께 해결하는, 개발자 커뮤니티 헬프로그래머스!
헬프로그래머스 (Helprogrammers)
- 헬프 + 프로그래머스 : 개발자들의 알고리즘 문제해결을 돕는다(HELP).
- 헬 + 프로그래머스 : 프로그래밍은 말그대로 헬(HELL) 이다.
Function
🛠 개발자에 의한, 개발자를 위한 기능!
- 도움을 구하고 싶은 알고리즘 질문을 게시하고, 댓글로 힌트를 주고 받을 수 있습니다.
- 댓글은 스포의 정도에 따라 상 중 하의 레벨로 나누어 작성됩니다.
- 유저가 보고싶지 않은 수준의 힌트가 스포되지 않도록 댓글은 가려진 상태로 제공되며, 원하는 레벨의 힌트만 열어볼 수 있습니다.
- 마크다운 에디터를 통해 게시글 및 댓글 작성시 가독성있는 코드를 작성할 수 있습니다.
- 모든 게시글과 댓글 작성시 작성자와 비밀번호를 입력해 수정, 삭제 전 유효성검사를 진행합니다.
시연을 하러 가볼까요?
https://www.youtube.com/watch?v=cDeqB5vbVzs
✨Code Review
[ edit state 변경 시 컴포넌트 변경 ]
function Question() {
const dispatch = useDispatch();
// qeustion state
const { question } = useSelector((state) => state.detail);
const [edit, setEdit] = useState(false);
const questionHints = hints?.filter(
(hint) => hint.questionId === question.id,
);
return (
<QuestionContainer>
{/* 상세 페이지 */}
<Detail setEdit={setEdit} edit={edit} />
{/* 댓글 */}
{!edit && (
<>
<AddHint question={question} />
<HintList questionHints={questionHints} key={question.id} />
</>
)}
</QuestionContainer>
);
}
export default Question;
Question 이라는 컴포넌트에서 edit 이라는 state의 기본값으로는 false입니다. 수정버튼이 클릭되면 setEdit으로 edit의 상태가 true가 되어 삼항연산자로 감싸주었던 상세페이지 컴포넌트가 변경되고, 댓글 컴포넌트를 지웁니다.
[ 수정버튼 클릭 ↔ 컴포넌트 변경 ]
// props로 받은 edit state
const Detail = ({ setEdit, edit }) => {
// 삭제 버튼
const deleteButton = (event, id) => {
event.preventDefault();
// const reCheck = window.confirm('정말 삭제하시겠습니까?'); // confirm 으로 재확인
if (writer.replace(/ /g, '') === '') {
alert('이름을 입력해주세요!');
focusWriter.current.focus();
return;
} else if (question.writer !== writer) {
alert('이름이 틀렸습니다!');
return;
} else if (password.replace(/ /g, '') === '' || password.length !== 4) {
alert('비밀번호는 4자리 숫자로 입력해주세요!');
focusPassword.current.focus();
return;
} else if (question.password !== Number(password)) {
alert('비밀번호가 틀렸습니다!');
return;
} else if (window.confirm('정말 삭제하시겠습니까?')) {
dispatch(__deleteDetail(id)); // DetailSlice >> deleteDetail (action)
navigation('/'); // main page로 돌아가기
} else {
return;
}
};
// 수정 버튼
const updateButton = (event) => {
event.preventDefault();
// 토글 수정, 완료
if (writer.replace(/ /g, '') === '') {
alert('이름을 입력해주세요!');
focusWriter.current.focus();
return;
} else if (question.writer !== writer) {
alert('이름이 틀렸습니다!');
return;
} else if (password.replace(/ /g, '') === '' || password.length !== 4) {
alert('비밀번호는 4자리 숫자로 입력해주세요!');
focusPassword.current.focus();
return;
} else if (question.password !== Number(password)) {
alert('비밀번호가 틀렸습니다!');
return;
}
setEdit(!edit);
};
return (
<>
{edit ? (
<UpdateComponent question={question} setEdit={setEdit} />
) : (
<Wrapper>{/* 컴포넌트 */}</Wrapper>
)}
</>
);
};
export default Detail;
props로 넘겨받은 setEdit 과 edit을 활용해 업데이트(수정 페이지)컴포넌트를 보여주거나, 기본 디테일(상세 페이지)컴포넌트를 보여줄 수 있습니다.
Trouble Shooting 🔥
import React, { useRef } from 'react';
const UpdateComponent = ({ question, setEdit }) => {
// ref = focusTitle
const focusTitle = useRef();
// 수정 완료(submit)
const onSubmitEditor = (id, updateQuestion) => {
if (title.replace(/ /g, '') === '') {
alert('제목을 입력해주세요!');
focusTitle.current.focus();
return;
} else if (content.replace(/ /g, '') === '') {
alert('내용을 입력해주세요!');
focusContent.current.focus();
return;
}
if (window.confirm('수정을 완료하시겠습니까??') === true) {
dispatch(__updateDetail({ id, updateQuestion }));
setEdit(false);
} else {
return;
}
};
return (
<InputTitle
value={title}
onChange={(e) => {
setTitle(e.target.value);
}}
ref={focusTitle}
type="text"
placeholder="제목을 입력해 주세요"
/>
);
};
어떤 문제가 발생했었나요?
코드에 직접 dom요소 접근(querySelector)하는 문제로, 원인모를 에러
어떻게 해결했나요?
useRef를 활용하여 요소 접근
- import
useRef - 변수에
useRef()할당 - 요소에
ref={변수명}속성 추가 - 변수명 호출하여 조작
helprogrammers 프로젝트 - useRef(리액트 훅)
Project Review
💬 사실은 말이조? 우리는 생각한대로 해내는 사람들이에요!
💬 사실은 말이조? 귀여운게 최고입니다.
💬 사실은 말이조? 정말 '4'실은 말이조였어요~!
💬 사실은 말이조? 디발자와 함께한답니다~
💬 사실은 말이조? 소는 아니죠..?? 🐴 🐮
💬 사실은 말이조? 계란말이죠??
