React JS
input의 value와 onChange 이벤트
개념
input에 value 속성을 지정하면 사용자가 input에 값을 입력해도 변경되지 않는다. 하지만 value={state}로 해두면(value에 변하는 값인 state나 props를 주면) 사용자의 입력에 따라 값이 변하도록 할 수 있다. 이때의 state는 input에 onChange 이벤트가 발생할 때 event의 target.value로 업데이트해준다. input에서 일어나는 onChange 이벤트는 보이는 value 값이 변하지 않아도 사용자가 입력하는 값을 받아오기 때문에 가능하다.
const [inputValue, setInputValue] = useState('');
const [newComments, setNewComments] = useState([]);
const commentInput = useRef(); // input에 직접 접근하여 value 값 바꾸기 위해
const getComment = event => {
setInputValue(event.target.value);
};
const addComment = event => {
event.preventDefault();
setNewComments([...newComments, inputValue]);
// 아래 둘 중 하나로 input 값 초기화
// event.target.reset();
// input.current.value="";
setInputValue('');
};
<form onSubmit={addComment} className="feedColumn">
<input
ref={commentInput} // useRef() 사용하는 방법
value={inputValue} // state로 value 변경하는 방법
onChange={getComment}
className="comment"
placeholder="댓글 달기..."
/>
<button
disabled={!inputValue}
className={`postButton${inputValue ? ' activeButton' : ' '}`}
>
게시
</button>
</form>
하지만 사용자가 입력하는 게 아니라, 자바스크립트 코드로 input의 value를 다른 값으로 지정하는 것은 onChange 이벤트로 감지하지 못한다. 예를 들어, input이 있는 form이 submit 되었을 때 실행되는 함수에서 form을 reset하거나 input의 value를 직접적으로 ""(빈 문자열)로 만들어주어도 input에서 onChange 이벤트는 발생하지 않는다.
만약 form을 reset하거나 input의 value를 코드로 초기화하는 것을 onChange가 감지할 수 있다면 addComment 함수에서 마지막에 setInputValue("");로 state의 값을 바꿔주지 않아도 getComment 함수의 작동으로 해결될 텐데 아쉽다. 찾아봤지만 input의 value를 state와 연동시켜놓고, 초기화는 setState()로 하는 것이 최선인 것 같다.
참고
- React에서 <input>을 쓸 때 주의할 것 https://velog.io/@towozy/React%EB%A5%BC-%EC%93%B0%EB%A9%B4%EC%84%9C-%EC%B0%A9%EA%B0%81%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%AA%87%EA%B0%80%EC%A7%80-%EC%9A%94%EC%86%8C-3kjukr898l
- [JS] onchange 이벤트 사용, value 가져오기 https://coding-restaurant.tistory.com/317
코드 카타
숫자들로 구성된 배열을 받아 높은 빈도순으로 k개의 숫자 반환하기
내 답안
function topK(nums, k) {
nums.sort();
let sameNums = [[]];
for(let i = 0; i < nums.length; i++) {
let current = sameNums.length-1
sameNums[current].push(nums[i])
if(nums[i] !== nums[i+1]) {
sameNums.push([])
}
}
sameNums.pop();
let descendNum = [];
for(let j = 0; j < sameNums.length; j++) {
descendNum.push({ num : sameNums[j][0], length : sameNums[j].length})
}
descendNum.sort((a,b) => b.length - a.length);
let result = [];
for (let l = 0; l < k; l++) {
result.push(descendNum[l].num);
}
return result;
}
topK([1,2,2,2,2,1,1,2,3,6,2,3], 2)
- 실수 : let array = [ ]; 일 때, array가 [ [e] ]이 되려면 e가 들어갈 [ ] 빈 배열을 만들어준 뒤에 array[0]으로 접근해서 e를 push할 수 있다. 그러지 않고 array[0]에 push하려고 하면 array[0]은 배열이 아니기 때문에 undefined 라며 오류가 난다.
혹시 빈 인덱스에 push 하면 자동으로 그 자리에 배열이 만들어지고 요소가 들어가려나 했다. - 배열.sort() : 배열의 요소를 특정 기준에 따라 정렬한다. 인자가 없을 땐 기본적으로 오름차순 정렬한다.
- 객체를 요소로 갖는 배열에서 특정 key의 값을 기준으로 정렬할 수 있다.
- sort((a,b) => a.key - b.key) : 각 객체 요소에서 key에 해당하는 값을 기준으로 비교하여 오름차순 정렬한다.
- sort((a,b) => b.key - a.key) : 각 객체 요소에서 key에 해당하는 값을 기준으로 비교하여 내림차순 정렬한다.
- 풀이 방법 : 같은 숫자끼리 배열에 묶어, 각각 숫자별 배열을 요소로 갖는 sameNums라는 새로운 배열을 만든다.
- 풀이
- 여러 개의 숫자가 무작위로 반복되는 형태의 배열 nums를 받아 오름차순으로 정렬한다.
- 같은 숫자가 연달아 나올 것이기 때문에, for문을 돌려 nums에서 연속된 요소가 같은 숫자일 경우 sameNums의 마지막 요소인 배열안에 담고, 다른 숫자일 경우 sameNums의 끝에 빈배열을 새로운 요소로 추가하여 그 안에 숫자를 담는다.
- nums의 마지막 요소는 다음 요소가 undefined이기 때문에 무조건 연속된 숫자가 일치하지 않는다는 결과를 얻고, sameNums의 끝에 빈 배열을 추가하게 된다. 그래서 for문이 끝난 후 sameNums의 마지막 요소를 제거한다.
- sameNums의 각 요소는 같은 숫자끼리 묶인 배열이다. 이 요소 각각에 접근하는 for문을 돌려, 키가 num이고 값이 해당 숫자인 property와 키가 length이고 값이 해당 숫자의 개수인 property를 갖는 객체를 descendNum이라는 배열에 요소로 담는다.
- 이로써 descendNum의 각 요소에 접근한 뒤, "num"과 "length"라는 키로 어떤 숫자가 몇 개나 들어있었는지 알 수 있다.
- descendNum 배열을 각 요소(객체)에서 "length" property의 값이 큰 순서대로(숫자가 등장한 횟수가 많은 순) 정렬한다.
- 재정렬된 descendNum 배열에서 k번째까지 요소를 가져와, 각 요소의 "num" 값을 배열에 담아 반환한다.
참고) [Javascript] 배열 정렬하기 (오름차순, 내림차순, 문자열, 객체) https://hianna.tistory.com/409
'TIL' 카테고리의 다른 글
[TIL-133~134] 위코드 34~5일차: React JS - Monster (0) | 2022.02.27 |
---|---|
[TIL-132] 위코드 33일차: JS 코드카타 (0) | 2022.02.25 |
[TIL-130] 위코드 31일차: React JS - 서버와 통신하기 / JS 코드카타 (0) | 2022.02.23 |
[TIL-129] 위코드 30일차: React JS - 리팩토링 / JS 코드카타 (0) | 2022.02.22 |
[TIL-128] 위코드 29일차: React JS - 댓글 달기 / JS 코드카타 (0) | 2022.02.21 |