Skip to content

Commit 593de56

Browse files
authored
v0.1.0 (#7)
* 잡다한 설정 수정 * plugin-client-redirects 추가 * docs 추가 * config 경로 수정 * redirect 문제 수정 * 사이드바 설정 * 댓글 기능을 위한 utterances 관련 로직 추가 * onBrokenLinks 값 수정 * url, organizationname, github 이름 수정 * 문서들 약간의 수정 * logo, favicon 수정 * blog 추가 * rss 를 위한 blog author 추가 * readme 수정 * useLinkClickHandler 추가 * footer 추가 * feedoptions type 수정 * 로고, 잡다한 파일 수정 * darkmode 대응 * Blog 에 댓글 기능 추가 * DocPage utterances 사용 부분 리팩토링 * useUtterance 가 Color mode 를 지원할 수 있도록 수정 * utterance 속성 수정 * docs 가벼운 수정
1 parent c530407 commit 593de56

File tree

72 files changed

+8722
-1254
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+8722
-1254
lines changed

README.md

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,3 @@
1-
# Website
1+
# Blog
22

3-
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4-
5-
### Installation
6-
7-
```
8-
$ yarn
9-
```
10-
11-
### Local Development
12-
13-
```
14-
$ yarn start
15-
```
16-
17-
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18-
19-
### Build
20-
21-
```
22-
$ yarn build
23-
```
24-
25-
This command generates static content into the `build` directory and can be served using any static contents hosting service.
26-
27-
### Deployment
28-
29-
Using SSH:
30-
31-
```
32-
$ USE_SSH=true yarn deploy
33-
```
34-
35-
Not using SSH:
36-
37-
```
38-
$ GIT_USER=<Your GitHub username> yarn deploy
39-
```
40-
41-
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
3+
Powered by [Docusaurus 2](https://docusaurus.io/), Hosted by [Vercel](https://vercel.com/)

blog/2019-05-28-first-blog-post.md

Lines changed: 0 additions & 12 deletions
This file was deleted.

blog/2019-05-29-long-blog-post.md

Lines changed: 0 additions & 44 deletions
This file was deleted.

blog/2021-08-01-mdx-blog-post.mdx

Lines changed: 0 additions & 20 deletions
This file was deleted.
-93.9 KB
Binary file not shown.

blog/2021-08-26-welcome/index.md

Lines changed: 0 additions & 25 deletions
This file was deleted.

blog/authors.yml

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
1-
endi:
2-
name: Endilie Yacop Sucipto
3-
title: Maintainer of Docusaurus
4-
url: https://github.com/endiliey
5-
image_url: https://github.com/endiliey.png
6-
7-
yangshun:
8-
name: Yangshun Tay
9-
title: Front End Engineer @ Facebook
10-
url: https://github.com/yangshun
11-
image_url: https://github.com/yangshun.png
12-
13-
slorber:
14-
name: Sébastien Lorber
15-
title: Docusaurus maintainer
16-
url: https://sebastienlorber.com
17-
image_url: https://github.com/slorber.png
1+
pumpkiinbell:
2+
name: Jongho Park
3+
url: https://github.com/pumpkiinbell
4+
image_url: https://avatars.githubusercontent.com/u/19240202?v=4
5+
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
date: 2022-07-09T21:42
3+
authors: pumpkiinbell
4+
---
5+
6+
# useLinkClickHandler
7+
8+
react-router 를 쓰다보면 종종 특정 컴포넌트를 클릭할 때 location 을 바꾸기 위해 `useNavigate` 를 활용합니다.
9+
10+
<!--truncate-->
11+
12+
예를 들면, 다음과 같은 코드입니다.
13+
14+
```js
15+
function Component() {
16+
const navigate = useNavigate();
17+
// ...
18+
19+
return (
20+
<Button
21+
onClick={(e) => {
22+
e.preventDefault();
23+
24+
navigate.to('~~~');
25+
}}
26+
/>
27+
);
28+
}
29+
```
30+
31+
위 코드는 우리가 원하는 요구사항을 대부분 충족시켜줍니다.
32+
33+
그러나, 이런 구현들을 직접하게 될 경우 예상치 못한 edge case 들이 발생하게 됩니다.
34+
35+
예를 들어 마우스의 휠 중간 버튼을 클릭 했을 때 새 탭이 열리거나, `command, ctrl` 등의 키와 함께 클릭 시 새 탭이 열려야 되는데 그렇지 못하는 문제들이 발생합니다.
36+
37+
react-router 는 이에 대응할 수 있는 `useLinkClickHandler` 라는 훅을 제공해줍니다.
38+
39+
## Usage
40+
41+
[useLinkClickHandler](https://reactrouter.com/docs/en/v6/hooks/use-link-click-handler) 는 react-router-dom 이 제공하는 `<Link>` 컴포넌트가 아닌, 커스텀한 navigator 를 구현할 때 click event handler 로 사용할 수 있는 함수를 반환해줍니다.
42+
43+
다음과 같이 사용합니다.
44+
45+
```js
46+
import { useHref, useLinkClickHandler } from 'react-router-dom';
47+
48+
const StyledLink = styled('a', { color: 'fuchsia' });
49+
50+
const Link = React.forwardRef(({ onClick, replace = false, state, target, to, ...rest }, ref) => {
51+
let href = useHref(to);
52+
let handleClick = useLinkClickHandler(to, {
53+
replace,
54+
state,
55+
target,
56+
});
57+
58+
return (
59+
<StyledLink
60+
{...rest}
61+
href={href}
62+
onClick={(event) => {
63+
onClick?.(event);
64+
if (!event.defaultPrevented) {
65+
handleClick(event);
66+
}
67+
}}
68+
ref={ref}
69+
target={target}
70+
/>
71+
);
72+
});
73+
```
74+
75+
참고로, `useHref` 는 접근성을 위해 basename 을 포함한 full path 를 반환해주는 훅입니다.
76+
77+
## Implementation
78+
79+
useLinkClickHandler 는 [다음과 같이 구현](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/index.tsx#L383-L423)되어 있습니다.
80+
81+
```js
82+
/**
83+
* Handles the click behavior for router `<Link>` components. This is useful if
84+
* you need to create custom `<Link>` components with the same click behavior we
85+
* use in our exported `<Link>`.
86+
*/
87+
export function useLinkClickHandler<E extends Element = HTMLAnchorElement>(
88+
to: To,
89+
{
90+
target,
91+
replace: replaceProp,
92+
state,
93+
}: {
94+
target?: React.HTMLAttributeAnchorTarget;
95+
replace?: boolean;
96+
state?: any;
97+
} = {}
98+
): (event: React.MouseEvent<E, MouseEvent>) => void {
99+
let navigate = useNavigate();
100+
let location = useLocation();
101+
let path = useResolvedPath(to);
102+
103+
return React.useCallback(
104+
(event: React.MouseEvent<E, MouseEvent>) => {
105+
if (
106+
event.button === 0 && // Ignore everything but left clicks
107+
(!target || target === "_self") && // Let browser handle "target=_blank" etc.
108+
!isModifiedEvent(event) // Ignore clicks with modifier keys
109+
) {
110+
event.preventDefault();
111+
112+
// If the URL hasn't changed, a regular <a> will do a replace instead of
113+
// a push, so do the same here.
114+
let replace =
115+
!!replaceProp || createPath(location) === createPath(path);
116+
117+
navigate(to, { replace, state });
118+
}
119+
},
120+
[location, navigate, path, replaceProp, state, target, to]
121+
);
122+
}
123+
```
124+
125+
몇 가지 주목해야 할 점이 있습니다.
126+
127+
[**_MouseEvent.button_**](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button#value)
128+
129+
`event.button` 은 마우스가 눌렸을 때 이벤트를 trigger 한 버튼이 어떤 것인지 눌렸는 지 확인할 수 있는 값입니다.
130+
131+
`event.button` 이 0 인 경우는 메인 버튼, 즉 마우스 왼쪽 버튼이 클릭되었음을 의미합니다.
132+
133+
`useLinkClickHandler` 는 클릭된 버튼이 마우스 왼쪽 버튼이 아니라면 별다른 동작을 하지 않습니다.
134+
135+
[**_target_**](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target)
136+
137+
anchor element 는 linked URL 을 보여줘야 할 때 **탭인지, 윈도우인지 (browsing context)** 보여주기 위한 속성값인 `target` 을 받을 수 있습니다.
138+
139+
target 으론 `_self, _blank, _parent, _top` 등의 속성이 있습니다.
140+
141+
`useLinkClickHandler` 는 target 이 `_self` 이거나, 받은 target 이 없는 경우 동작을 수행합니다.
142+
143+
[**_isModifiedEvent_**](https://github.com/remix-run/react-router/blob/381e90515289756e40f1620a4196dbd3cad300e9/packages/react-router-dom/index.tsx#L247-L249)
144+
145+
isModifiedEvent 는 클릭 시 `ctrl, command` 등의 키와 함께 눌렸는지 확인하는 함수입니다.
146+
147+
```js
148+
function isModifiedEvent(event: React.MouseEvent) {
149+
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
150+
}
151+
```
152+
153+
`useLinkClickHandler``modifier` 키들과 함께 클릭이 된 경우 동작을 수행하지 않습니다.
154+
155+
**_replace_**
156+
157+
주석에도 설명되어 있다시피 만약, URL 이 변경되지 않았는데 linkClickHandler 가 호출이 되는 경우 push 대신 replace 로 동작을 수행하게 됩니다.
158+
159+
## 정리
160+
161+
컴포넌트를 `a tag` 로 만들고 `useLinkClickHandler` 를 활용한 컴포넌트를 만들면 접근성을 준수한 `SPA` 라우팅 컴포넌트를 만들 수 있습니다.

0 commit comments

Comments
 (0)