📌 오늘 진행 사항
- weekly 키보드 포커스 시 아이템 두개씩 넘어가는 문제 해결
- prettier, eslint 팀프로젝트에 적용
📌 New 지식
- prettier 적용 방법
.prettierrc
에 규칙 추가- 모든 파일에 한번에 prettier 적용하기 :
npx prettier --write "src/**/*.{js,jsx,ts,tsx,json,css,md}”
- vscode에 자동 적용하기
Prettier - Code formatter
확장 프로그램 설치- .vscode/setting.json에 아래같이 추가
1. prettier 패키지 설치 :
npm install --save-dev prettier
ex)
{ "singleQuote": true, "semi": true, "printWidth": 100, "tabWidth": 2, "trailingComma": "all", "arrowParens": "always" }
{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode" }
- eslint 적용 방법
- vscode에 자동 적용하기
ESLint
확장 프로그램 설치
1. eslint, eslint-plugin-react 설치하기 : npm install --save-dev eslint eslint-plugin-react
📌 문제 및 해결 사항
searchbar
import { SearchForm, SearchIcon } from './SearchBar.Styles'; import imgSearchDefault from '/src/assets/images/icon/i_search_default.png'; import imgSearchFocused from '/src/assets/images/icon/i_search_focused.png'; import imgSearchTyping from '/src/assets/images/icon/i_search_typing.png'; import { FocusContext, setFocus, useFocusable } from '@noriginmedia/norigin-spatial-navigation'; import useSearchStore from '../../../../store/useSearchStore'; import SearchInput from './SearchInput'; const SearchBar = ({ value }) => { const { isInputTyping, isRecentSearchOn } = useSearchStore(); const { ref: formRef, hasFocusedChild, focusKey, } = useFocusable({ focusKey: 'SearchForm', focusable: false, trackChildren: true, preferredChildFocusKey: 'SearchBar', onArrowPress: (dir) => { if (dir === 'down') { console.log('흠'); if (isRecentSearchOn) { setFocus('recent'); } else { setFocus('Recommendation'); } } }, }); console.log('saveLastFocusedChildKey) ', hasFocusedChild); return ( <FocusContext.Provider value={focusKey}> <SearchForm ref={formRef} $isTyping={isInputTyping} $isFocused={hasFocusedChild} onMouseOver={setFocus('SearchBar')} onMouseLeave={setFocus} style={{ backgroundColor: hasFocusedChild ? 'orange' : 'gray' }} > <SearchIcon src={ hasFocusedChild ? isInputTyping ? imgSearchTyping : imgSearchFocused : imgSearchDefault } /> <SearchInput defaultValue={value} /> </SearchForm> </FocusContext.Provider> ); }; export default SearchBar;
📌 모호하게 알고 넘어가는 것이 없나요? (Y/N)
input
import { setFocus, useFocusable } from '@noriginmedia/norigin-spatial-navigation'; import { SearchInputBox } from './SearchBar.Styles'; import { useEffect } from 'react'; import useSearchStore from '../../../../store/useSearchStore'; import { useNavigate } from 'react-router-dom'; const SearchInput = ({ defaultValue }) => { const { isInputTyping, setIsInputTyping } = useSearchStore(); const navigation = useNavigate(); const goToSearch = (keyword) => navigation(`?q=${keyword}`); const handleSubmit = () => { const searchWord = inputRef.current.value; if (searchWord) { goToSearch(searchWord); } }; const { ref: inputRef, focused, focusSelf, } = useFocusable({ focusKey: 'SearchBar', onBlur: () => {}, forceFocus: true, onEnterPress: isInputTyping ? handleSubmit : () => setIsInputTyping(true), }); const handleKeyDown = (e) => { // 좌우 방향키일 때 (keyCode: 37=left, 39=right) if (e.target === inputRef.current && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) { // 인풋 내부의 커서 이동만 하고, 이벤트 전파 막기 e.stopPropagation(); // 굳이 preventDefault하지 않아도 인풋은 자체적으로 커서 이동 처리합니다 } }; const preventMax = () => { if (inputRef.current.value.length > 255) { inputRef.current.value = inputRef.current.value.slice(0, 255); } }; useEffect(() => { if (inputRef.current && isInputTyping) { const inputValueLength = inputRef.current.value.length; inputRef.current.setSelectionRange(inputValueLength, inputValueLength); inputRef.current.focus(); } else if (inputRef.current && !isInputTyping) { inputRef.current.blur(); } }, [inputRef.current, isInputTyping]); useEffect(() => { focusSelf(); }, []); return ( <SearchInputBox ref={inputRef} onKeyDown={handleKeyDown} defaultValue={defaultValue ? defaultValue : ''} placeholder="Search your destination or interest." onChange={preventMax} /> ); }; export default SearchInput;