본문 바로가기

TIL

[TIL-131] 위코드 32일차: React JS - 위스타그램 마무리 / JS 코드카타

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()로 하는 것이 최선인 것 같다.

 

참고

 


코드 카타

 

숫자들로 구성된 배열을 받아 높은 빈도순으로 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라는 새로운 배열을 만든다.   
  • 풀이
    1. 여러 개의 숫자가 무작위로 반복되는 형태의 배열 nums를 받아 오름차순으로 정렬한다.
    2. 같은 숫자가 연달아 나올 것이기 때문에, for문을 돌려 nums에서 연속된 요소가 같은 숫자일 경우 sameNums의 마지막 요소인 배열안에 담고, 다른 숫자일 경우 sameNums의 끝에 빈배열을 새로운 요소로 추가하여 그 안에 숫자를 담는다.
    3. nums의 마지막 요소는 다음 요소가 undefined이기 때문에 무조건 연속된 숫자가 일치하지 않는다는 결과를 얻고, sameNums의 끝에 빈 배열을 추가하게 된다. 그래서 for문이 끝난 후 sameNums의 마지막 요소를 제거한다.
    4. sameNums의 각 요소는 같은 숫자끼리 묶인 배열이다. 이 요소 각각에 접근하는 for문을 돌려, 키가 num이고 값이 해당 숫자인 property와 키가 length이고 값이 해당 숫자의 개수인 property를 갖는 객체를 descendNum이라는 배열에 요소로 담는다.
      • 이로써 descendNum의 각 요소에 접근한 뒤, "num"과 "length"라는 키로 어떤 숫자가 몇 개나 들어있었는지 알 수 있다.
    5. descendNum 배열을 각 요소(객체)에서 "length" property의 값이 큰 순서대로(숫자가 등장한 횟수가 많은 순) 정렬한다.
    6. 재정렬된 descendNum 배열에서 k번째까지 요소를 가져와, 각 요소의 "num" 값을 배열에 담아 반환한다.

 

참고) [Javascript] 배열 정렬하기 (오름차순, 내림차순, 문자열, 객체) https://hianna.tistory.com/409