이런 식으로 렌더링되자마자 input에 focus가 잡히고,
코드를 입력할 수도 있고, 지울 수도 있는 그런 컴포넌트를 만들어보았습니다!
저한테는 꽤나 챌린징 요소였던 터라 기록해보려고 합니다.
물론 조금의 야매(?) 적인 부분도 있지만 ..! ㅎㅎ
const InputBlock = forwardRef(({ code, inputRef }, ref) => {
return (
<s.Wrapper>
<s.Block onClick={() => inputRef.current.focus()}>{code[0]}</s.Block>
<s.Block>{code[1]}</s.Block>
<s.Block>{code[2]}</s.Block>
<s.Block>{code[3]}</s.Block>
<s.Block>{code[4]}</s.Block>
<s.Block>{code[5]}</s.Block>
</s.Wrapper>
);
});
export default InputBlock;
code를 넣어주면 한글자씩 display해주는 컴포넌트 입니다.
onClick을 통해 input 박스에 focus 해주는 기능도 넣어놨습니다.
style은 아래와 같으니 참조만 해주세요!
export const Wrapper = styled.div`
display: flex;
gap: 4px;
`;
export const Block = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 3.5rem;
height: 4.5rem;
border-radius: 5px;
border: 1px solid rgba(255, 255, 255, 0.5);
background: linear-gradient(
315deg,
rgba(255, 255, 255, 0.7) 2.58%,
rgba(255, 255, 255, 0.3) 97.92%
);
backdrop-filter: blur(5px);
text-align: center;
font-size: 18px;
font-weight: 700;
line-height: 150%; /* 27px */
letter-spacing: -0.18px;
`;
const [codeArr, setCodeArr] = useState('');
const inputRef = useRef(null);
const handleCodeInput = (e) => {
const input = e.target.value;
const numericInput = input.replace(/\D/g, ''); // 숫자가 아닌 문자 제거
if (numericInput.length <= 6) setCodeArr(numericInput);
};
먼저 codeArr
을 상태로 저장해주고,
input태그는 숨겨줄 거기 때문에 useRef를 통해 inputRef
에 참조값을 저장해둡니다.
input 태그에 onChanage로 handleCodeInput
을 설정해줍니다.
해당 함수는 숫자가 아닌 문자값이 들어오면 저장하지 않는 로직을 포함합니다.
추가적으로 codeArr
값을 업데이트해줍니다.
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
useEffect를 통해 mount되자마자 input 박스에 focus될 수 있도록 해줍니다.
<s.CodeBlock>
<s.CodeInput
id='code-input'
ref={inputRef}
type='text'
value={codeArr}
onChange={handleCodeInput}
/>
<InputBlock code={Array.from(codeArr)} inputRef={inputRef} />
</s.CodeBlock>
export const CodeBlock = styled.div`
display: flex;
`
export const CodeInput = styled.input`
opacity: 0;
width: 100px;
position: absolute;
`
CodeInput 은 opacity: 0;
으로 숨겨주고 만들어놓은 InputBlock
컴포넌트를 렌더링해주면 끝 !!
원래 display: none;
을 했었는데 그러면 아예 focus가 되지 않는 문제가 발생했다.
opacity: 0;
으로 숨겨주면 display는 되지만 사용자의 눈에만 안 보이는 것이기 때문에 의도한 대로 구현할 수 있다.
이상 기록 끝!