항해 99 리엑트 2주차 과제는 백과 협업하여, 프로젝트를 만들기였습니다. 한번은 도전 하고 싶었던 개발 블로그라는 주제에, 적은 시간에 높은 완성도를 낼 수 있는 클론 코딩을 결합하여, velog 클론 코딩을 기획하여 1주일동안 프로젝트를 진행하였습니다.
회원가입 페이지 | 로그인 페이지 |
---|---|
<input
name="loginId"
value={form.loginId}
autoComplete="username"
id="loginId"
onChange={onChangeInputHandler}
ref={inputLoginId}
placeholder="영문 소문자, 숫자가 모두 포함된 4~12자리로 작성해주세요."
></input>
<Button
margin="0 0 0 15px"
fontFamily="bold"
onClick={onClickCheckUsername}
>
중복체크
</Button>
</div>
{/* 아이디 규칙 적용 경고*/}
{!/^(?=.*\d)(?=.*[a-z])[0-9a-z]{4,12}$/.test(form.loginId) &&
form.loginId && (
<p>영문 소문자, 숫자가 모두 포함된 4~12자리로 작성해주세요.</p>
)}
<label htmlFor="password">비밀번호</label>
<input
type="password"
name="password"
autoComplete="new-password"
value={form.password}
id="password"
onChange={onChangeInputHandler}
placeholder="영문, 숫자, 특수문자가 모두 포함된 8~16자리로 작성해주세요."
></input>
{/* 비밀번호 규칙 적용 경고 수정 필요*/}
{!/^(?=.*[a-zA-z])(?=.*[0-9])(?=.*[$`~!@$!%*#^?&\\(\\)\-_=+]).{8,16}$/.test(
form.password
) &&
form.password && (
<p>영문, 숫자, 특수문자가 모두 포함된 8~16자리로 작성해주세요.</p>
)}
react-markdown
이라는 라이브러리를 활용하여, 마크다운 작성 활성화import React from "react";
import styled from "styled-components";
import ReactMarkdown from "react-markdown";
// -- 중간줄 구현하기
import remarkGfm from "remark-gfm";
// code 보여주기
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
function BlockQutoe(children) {
return (
<BlockQutoeStyle>
<span>{children.children}</span>
</BlockQutoeStyle>
);
}
const MarkdownRender = ({
markdown,
height,
fontsize,
margin,
overflow,
cursor,
onClick,
color,
}) => {
return (
<MarkDownStyle
fontsize={fontsize}
color={color}
margin={margin}
overflow={overflow}
cursor={cursor}
onClick={onClick}
>
<TableContainer height={height}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
children={markdown}
components={{
blockquote: BlockQutoe,
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || "");
return !inline && match ? (
<SyntaxHighlighter
children={String(children).replace(/\n$/, "")}
language={match[1]}
{...props}
/>
) : (
<code className={className} {...props}>
{children}
</code>
);
},
}}
></ReactMarkdown>
</TableContainer>
</MarkDownStyle>
);
};
const MarkDownStyle = styled.div`
font-size: ${({ fontsize }) => fontsize || "16px"};
line-height: 2.5rem;
overflow-y: ${({ overflow }) => overflow || "auto"};
margin: ${({ margin }) => margin || "0"};
color: ${({ color }) => color || "gray"};
cursor: ${({ cursor }) => cursor || "default"};
`;
// 표일 때
const TableContainer = styled.div`
height: ${({ height }) => height || "200px"};
width: 100%;
img {
width: 50%;
height: 100%;
object-fit: cover;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
border: 1px solid #ccc;
padding: 5px;
}
`;
const BlockQutoeStyle = styled.blockquote`
width: 97%;
padding: 0 0.8rem;
border-left: 5px solid var(--color-deep-red);
margin-left: 0;
background-color: var(--color-light-gray);
color: white;
span {
color: white;
background-color: transparent;
}
`;
export default MarkdownRender;
// 테그 인풋 state 가져오기
const onChangeTagHandler = (event) => {
event.preventDefault();
const { name, value } = event.target;
dispatch(
changeField({
form: "editPost",
key: name,
value,
})
);
};
//-- 엔터칠 때 태그 리스트로 들어가게 하기 --//
const onKeyUp = (event) => {
if (event.target.value.length !== 0 && event.key === "Enter") {
submitTagItem();
}
};
const submitTagItem = () => {
let updateTagList = [...form.tags];
updateTagList.push(form.tag);
dispatch(
changeField({
form: "editPost",
key: "tags",
value: updateTagList,
})
);
dispatch(
changeField({
form: "editPost",
key: "tag",
value: "",
})
);
};
const deleteTagItem = (event) => {
const deleteTagItem = event.target.innerText;
const filteredTagList = form.tags.filter(
(tagItem) => tagItem !== deleteTagItem
);
dispatch(
changeField({
form: "editPost",
key: "tags",
value: filteredTagList,
})
);
백과 함께 협업하게 되어 무척 즐거웠습니다. 협업 과정에서 다양하게 시도할 수 있어서 즐거웠고, 시각적으로 눈에 띄는 기술들을 적용해 볼 수 있어서 더 재밌고 완성도 높다고 느껴지는 프로젝트였습니다.