๐Ÿฅฐ react popover์ฐฝ์—์„œ input์— autoFocus ์ ์šฉํ•˜๊ธฐ

Solmiiยท2020๋…„ 10์›” 19์ผ
5

Next

๋ชฉ๋ก ๋ณด๊ธฐ
1/1
post-thumbnail

๋ธ”๋กœ๊ทธ์•ผ...์•ˆ๋…•....?
๊ทผ ๋‘๋‹ฌ๋งŒ์ด๊ตฌ๋‚˜....๐Ÿ˜… ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹....

๋ณ€๋ช…์„ ํ•ด๋ณด์ž๋ฉด ์š”์ƒˆ ์•ผ๊ทผ ์ง€์˜ฅ + ํšŒ์‚ฌ ์ ์‘ ๊ธฐ๊ฐ„์„ ๊ฑฐ์น˜๋Š๋ผ ์ข€ ์ •์‹ ์ด ์—†์—ˆ๋Š”๋ฐ, ์ด์ œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์—ด์‹ฌํžˆ ์จ๋ณผ๊ฑฐ๋‹ค.
์ง„์งœ๋ฃจ....๐Ÿ˜ญ

์•„๋ฌดํŠผ, Next.js์—์„œ ํด๋ฆญ์‹œ popover(a.k.a modal)๊ฐ€ ๋œจ๋Š” search ์ฐฝ์„ ๊ตฌํ˜„ํ•˜๋ฉด์„œ
autoFocus, autoSelect๋ฅผ ์ ์šฉํ–ˆ๋Š”๋ฐ ์ด์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. (์—„์ฒญ ์‰ฌ์›€ ์ฃผ์˜๐Ÿ˜ณ)


๐Ÿ‘‰ popover์— autoFocus ์ ์šฉํ•˜๊ธฐ

<input autofocus />

input์ฐฝ์— ์ด๋ ‡๊ฒŒ๋งŒ ์ž…๋ ฅํ•ด์ฃผ๋ฉด component๊ฐ€ ๋งˆ์šดํŠธ ๋œ ํ›„์— ์ž๋™์œผ๋กœ focus๊ฐ€ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ, open ์—ฌ๋ถ€๋ฅผ state๋กœ ๊ด€๋ฆฌํ•˜๋Š” popover์—์„œ๋Š” ์ „ํ˜€ ๋จนํžˆ์ง€ ์•Š๋Š”๋‹ค....
์‹ค์ œ๋กœ ๋ธŒ๋ผ์šฐ์ € console์ฐฝ์— document.activeElement ๋กœ ํ˜„์žฌ ์„ ํƒ๋œ element๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด,
input์ฐฝ์ด ์•„๋‹ˆ๋ผ popover component ์ „์ฒด๊ฐ€ ์ฐํžˆ๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋ญ”๊ฐ€ ๊ฒ๋‚˜ ๋ณต์žกํ•ด ๋ณด์ด๋Š”๋ฐ ๊ทธ๋ƒฅ material-ui popover์ž„

ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค.
ํŠน์ • ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ (or ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ)
ํŒ์—…์ฐฝ์ด ๋œจ๋ฉด, ํŒ์—…์ฐฝ ๋‚ด์—์„œ useRef๋ฅผ ์ด์šฉํ•ด์„œ input์ฐฝ์— ๊ฐ•์ œ๋กœ focus๋ฅผ ์ฃผ๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ, useRef์— ๋Œ€ํ•ด ์™„๋ฒฝํžˆ ์ดํ•ดํ–ˆ๋ƒ ํ•˜๋ฉด ๊ทธ๊ฑด Nope......
์ฃผ๋ง๋™์•ˆ ์ข€ ํŒŒ๋ด์•ผ๊ฒ ๋‹ค๐Ÿ˜ญ


import React, { useEffect, useRef } from 'react';

๋จผ์ € useEffect์™€ useRef๋ฅผ react์—์„œ Import ํ•ด์˜ค๊ณ ,
popover component ๋‚ด์—์„œ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ค€๋‹ค!

function Popover() {
  const searchElement = useRef(null); // DOM ์š”์†Œ๋ฅผ searchElement์— ํ• ๋‹น
  
  ...
  
  useEffect(() => {
    if (searchElement.current) { // ํ• ๋‹นํ•œ DOM ์š”์†Œ๊ฐ€ ๋ถˆ๋Ÿฌ์ง€๋ฉด (๋งˆ์šดํŠธ ๋˜๋ฉด)
      searchElement.current.focus(); // focus ํ• ๋‹น!
    }
  }, []);
  
  ...
  
 return(
    <input ref={searchElement} /> // input์— ์œ„์—์„œ ์„ ์–ธํ•œ searchElement ์ „๋‹ฌ
  )
}

์šฐ์™•๐Ÿ˜ ์งฑ ์ž˜๋จ~!!


๐Ÿ‘‰ popover์— autoSelect ์ ์šฉํ•˜๊ธฐ

์ด๊ฑด ๋” ์‰ฝ๋‹น....
input์ฐฝ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ(=focus ๋œ ํ›„์—) ์ž…๋ ฅ๋œ ๋ชจ๋“  ๋‚ด์šฉ์„ ์ž๋™์œผ๋กœ ์ „์ฒด์„ ํƒ ํ•ด์ฃผ๋Š”๊ฑด๋ฐ,
input ํƒœ๊ทธ์˜ onFocus ์†์„ฑ์„ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ด๋ณผ๊ฑฐ๋‹ค.

<input ref={searchElement} onFocus={(e) => e.currentTarget.select()} />

์œ„์—์„œ ๋งŒ๋“  input์ฐฝ์— ์œ„ ๋‚ด์šฉ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค!
์™„์ „ ์‰ฝ๊ฒŒ Done๐Ÿ˜๐Ÿ˜๐Ÿ˜๐Ÿ˜!!!

flow๋„ ๊ฐ„๋‹จํ•˜๋‹ค. input์— onFocus event๊ฐ€ ์‹คํ–‰๋˜๋ฉด, event๊ฐ€ ์ผ์–ด๋‚œ currentTarget์„ ๋ฐ›์•„์™€์„œ, ๊ฐ•์ œ๋กœ select ํ•ด์ค€๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋ฅผ onFocus={(e) => console.log("target : ", e.currentTarget)} ์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ณด๊ณ  console์ฐฝ์„ ํ™•์ธํ•ด๋ณด๋ฉด?


์š”๋กœ์ฝ”๋กฌ~~ ์‹ค์ œ event๊ฐ€ ์ผ์–ด๋‚œ input์ฐฝ์ด ์ž˜ ์„ ํƒ๋œ๋‹ค!


์—ฌ๊ธฐ๊นŒ์ง€ ๊ตฌํ˜„ํ•˜๊ณ ๋‚˜๋ฉด ์ด๋Ÿฐ ๋ชจ์Šต์ด ๋œ๋‹ค!

์‰ฝ์ง€๋งŒ ๋ฟŒ๋“ฏํ•จ์€ ํฐ.... ์ €๋…ธ๋™ ๊ณ ํšจ์œจ ์ด๋ฒคํŠธ์˜€๋”ฐ ๐Ÿ‘

profile
ํ•˜๋ฃจ๋Š” ์น˜์—ดํ•˜๊ฒŒ ์ธ์ƒ์€ ์—ฌ์œ ๋กญ๊ฒŒ

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2020๋…„ 10์›” 22์ผ

ref ์–˜๊ธฐ ๋‚˜์™€์„œ ๋ง์ธ๋ฐ ์ตœ๊ทผ์— ๋ณด๋‹ˆ ๋ฆฌ์•กํŠธ ref ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ์ƒ๊ฐ๋ณด๋‹ค ๋ณ„๊ฑฐ ์—†๋”๋ผ๊ณ ์š”... ๊ทธ๋ƒฅ ๊ฐ์ฒด ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ  Object.seal()๋กœ current ์‚ญ์ œ ๋ชปํ•˜๋„๋ก ๋ด‰์ธํ•˜๊ณ  ๋.

import type {RefObject} from 'shared/ReactTypes';
// an immutable object with a single mutable value
export function createRef(): RefObject {
  const refObject = {
    current: null,
  };
  if (__DEV__) {
    Object.seal(refObject);
  }
  return refObject;
}
๋‹ต๊ธ€ ๋‹ฌ๊ธฐ