const [tempUsername, setTempUsername] = useState(username)
<Username>
{isEditing ? (
<>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<input
style={{ fontSize: '16px', fontWeight: '700', textAlign: 'center', padding: 0, margin: 0 }}
value={tempUsername}
onChange={handleInputChange}
onBlur={handleInputBlur} // (옵션) input 바깥을 클릭했을 때 변경 적용
onKeyUp={handleInputKeyUp}
autoFocus // input이 활성화될 때 자동으로 포커스
/>
<span style={{ fontSize: '12px', fontWeight: '500', textAlign: 'center' }}>
{byte}byte / 20byte
</span>
</div>
</>
) : (
<>
{username}
<FiEdit2
onClick={handleEditClick}
style={{ paddingTop: '5px', color: '#a1a1a1', cursor: 'pointer' }}
/>
</>
)}
</Username>
useEffect(() => {
setTempUsername(username);
setByte(getByteLength(username))
}, [username]);
const [isEditing, setIsEditing] = useState(false); // username을 수정하는 중인지 상태
const [byte, setByte] = useState(getByteLength(username));
const [tempUsername, setTempUsername] = useState(username) // 임시 username 저장
useEffect(() => {
setTempUsername(username);
setByte(getByteLength(username))
}, [username]);
//20byte 길이 검사하는 함수 - 한글은 3byte, 영문 및 숫자는 1byte
function getByteLength(str: any) {
return str.split('').reduce((byteLength: any, char: any) => {
const charCode = char.charCodeAt(0);
if (charCode <= 0x7f) {
return byteLength + 1;
} else if (charCode <= 0x7ff) {
return byteLength + 2;
} else if (0xd800 <= charCode && charCode <= 0xdbff) {
// Surrogate pair: These take 4 bytes in UTF-8 and 2 chars in UCS-2
// (Assume next char is the other [valid] half and just skip it)
return byteLength + 4;
} else {
// Other characters are 3 bytes in UTF-8
return byteLength + 3;
}
}, 0);
}
// 정규식을 사용하여 허용된 문자 및 기호만 입력되게 하는 로직
const isValidInput = (input: any) => {
const pattern = /^[A-Za-z0-9_.가-힣]*$/;
return pattern.test(input);
};
const handleEditClick = () => {
setIsEditing(true);
};
const handleInputChange = (e: any) => {
const inputValue = e.target.value;
const inputByte = getByteLength(inputValue);
if (getByteLength(inputValue) <= 20 && isValidInput(inputValue)) {
setTempUsername(inputValue);
setByte(inputByte);
}
console.log(tempUsername)
console.log(username)
};
const handleInputBlur = async () => {
// 사용자가 input 바깥을 클릭했을 때 변경을 적용할 경우 아래 코드 추가
await updateUsername();
setIsEditing(false);
// setTempUsername(tempUsername);
setUsername(tempUsername);
};
const handleInputKeyUp = async (e: any) => {
if (e.key === 'Enter') {
await updateUsername();
setIsEditing(false);
// setTempUsername(tempUsername);
setUsername(tempUsername);
}
};
//닉네임 변경
const updateUsername = async () => {
// tempUsername이 빈 문자열이면 업데이트를 건너뛴다.
if (!tempUsername.trim()) {
setTempUsername(username); // 현재 username으로 tempUsername을 리셋한다.
return;
}
// dispatch
dispatch(setUsername(tempUsername));
// 서버 업데이트
try {
const response = await axios.patch(`${APIURL}/members/username`, tempUsername, {
headers: {
Authorization: accessToken,
'Refresh-Token': refreshToken,
},
params: {
username: tempUsername, // 쿼리 파라미터로 username 추가
},
});
console.log(username);
console.log(tempUsername)
if (response.status === 200) {
console.log(response.data);
dispatch(setUsername(tempUsername));
}
} catch (error) {
console.log(error);
}
};