ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React] section 4, 5
    Frontend/React 2023. 10. 30. 19:28

    컴포넌트의 이벤트 함수

    ~Handler 방식으로 명명하기

    State

    state가 아닌 일반 변수들은 재평가를 트리거하지 않는다.

    useState

    이 함수는 리액트 라이브러리가 제공하는 것으로 값을 상태로 정의할 수 있도록 해주어 값에 변화가 생기면 다시 호출되는 컴포넌트 함수에 반영이 된다.
    리액트 훅이다.
    함수 안에서 사용되어야 하고, 중첩 함수 안에서도 호출될 수 없다.
    useState는 배열을 반환한다.

      const [title, setTitle] = useState(expenseTitle);

    첫번째 값은 관리되는 해당 값에 대한 포인터,
    두번째 값은 나중에 새 값을 설정할 때 호출할 함수이다.

    컴포넌트를 한 번 이상 생성한다해도 상태는 별개이다.
    (중요) 상태는 컴포넌트 인스턴스 별로 구분된다!
    어플리케이션에 반응성을 부여하는 건 state!

    왜 상태에 const를 할당할까?

    우리가 직접 변수 자체를 변경할 일이 없고 리액트에게 상태 관리를 맡긴다.
    우리는 함수를 호출할 뿐이기에 상수를 사용하는 것은 좋은 생각!

    onChange() 이벤트

    모든 인풋 타입에 같은 이벤트를 사용할 수 있다는 장점 (ex 드롭다운)

    발생한 이벤트를 설명해주는 event 객체를 얻는다.
    event.target은 단순히 이벤트가 발생한 DOM 요소를 지목하기만 한다. (ex input)
    가장 중요한 것은 event.target.value 프로퍼티 -> 이벤트가 발생되는 순간에 입력되어 있는 값이 들어있다.

    input에 대한 값을 읽는다면 언제나 문자열이다. (useState시 문자열로 초기화하는 이유)

    useState()를 한 번만 쓰는 법

    const [userInput, setUserInput] = 
    useState({enteredTitle : '', enteredAmount : '', enteredDate : ''});
    
    setUserInput({
    ...userInput,
    enteredTitle : event.target.value,
    })

    setState 할 때 모든 데이터를 확실히 set 시켜야 한다. 아니면 다른 키는 버리는 셈!
    ... -> 전개 연산자 사용하기! (중요)
    -> 이렇게 업데이트 하는게 사실 바람직한 방식은 아니다.
    이전 상태에 의존하고 있기 때문

    -> 상태를 업데이트 할 때, 그리고 이때 이전 상태에 의존할 경우 위와 같은 방식이 아닌 상태 업데이트 함수의 대체 양식을 사용해야 한다.
    아래와 같은 방법 사용해야 함!

    중요! - 이전 상태에 의존하여 상태를 업데이트하는 안전한 방법 (prevState)

    setUserInput((prevState) => {
    return {...prevState, enteredTitle : event.target.value };
    });

    이유 : 리액트는 상태 업데이트를 즉시 처리하지 않고 예약한다.
    그래서 이론적으로 다수의 상태 업데이트를 동시에 예약할 경우 오래되거나 잘못된 상태 스냅샷에 의존하게 될 수도 있다.
    그러나 위와 같은 방식을 행하면 리액트가 내부함수에서 제공하는 상태 스냅샷이 항상 최신 상태 스냅샷이 되도록 보장해준다.
    그래서 이것이 안전한 방법이다.

    하나의 changeHandler 만들기 (공용 함수)

    단 하나의 함수로 인풋 요소 전부를 대상으로 발생하는 onChange 이벤트를 처리하기

    const inputChangeHandler = (identifier, value) => {
    	if (identifier === 'title') {
    		setEnteredTitle(value);
    	} else if ... {
    	} ...
    }

    onChange event 에 연결하면 event 객체를 넘겨주지 identifier, value를 넘겨주지 않기 때문에 제대로 작동하지 않는다.
    -> 화살표 함수를 넘겨 해결할 수 있다.

    <input type = 'text' onChange=
    {(event) =>{inputChangeHandler('title', event.target.value)}} />

    이 화살표 함수는 인풋에 변경이 발생할 때마다 실행된다.
    화살표 함수를 이용하여 우리가 만든 handler 함수를 수동으로 실행시켜 준다.
    이렇게 화살표 함수로 감싸는 방식으로 함수가 어떻게 호출되는지를 개발자가 직접 정할 수 있게 된다.

    event.preventDefault()

    <form onSubmit={submitHandler}>
    ...
      <button type="submit">Add Expense</button>
          ...
    </form>

    -> 브라우저의 기본 기능이고 이 기능의 문제점은 페이지가 다시 로딩된다는 것! (중요)
    우리는 자바스크립트로 처리를 하고 직접 데이터를 수집하고 모아서 뭔가를 하길 원한다.
    우리는 이 기능을 비활성화 시킬 수 있다.
    이것이 event.preventDefault()
    -> 이 메소드는 자바스크립트의 기본 메서드이고 리액트와 관련된 것은 없다.
    -> 요청이 자동으로 발생되는 기능을 막아 페이지가 다시 로딩되지 않게 만든다.
    -> 요청을 어디에도 보내지 않고 상황을 처리할 수 있다.

    양방향 바인딩 (중요! - 리액트의 핵심 개념)

    인풋 요소에 발생하는 변경사항을 수신하는 것 뿐 아니라 인풋 요소에 새 값을 넣을 수 있다.
    -> value 속성을 추가하면 된다.

    <input type="text" value={enteredTitle} onChange={titleChangeHandler} />

    인풋에 발생한 변경 사항을 수신해 상태를 업데이트 하는 것 뿐 아니라 상태를 다시 인풋 요소에 전달해서 상태가 바뀌었을 때 인풋 요소도 바꿔 준다.

    자식-부모 컴포넌트 통신

    인풋 요소 또한 하나의 컴포넌트이다.
    리액트가 제공하는 컴포넌트이고 DOM에는 인풋 요소로 전달되는 컴포넌트

    속성은 부모와 자식 사이에서만 전달이 가능하고 중간 컴포넌트를 건너뛸 수 없다.

    우리가 전달하는 것은 함수 포인터이다. (핵심)

    <ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
    props.onSaveExpenseData(newExpense);

    상태 위로 올리기

    자식 컴포넌트에서 데이터를 올리는 것 그리고 그건 부모 컴포넌트에서 활용하거나 그 부모의 다른 자식 컴포넌트에게 전달할 수 있다.

    파생된 값

    설정하는 상태가 결국 다른 상태와 직접적으로 연결된다면 별도의 상태로 관리하는 건 좋지 않다.
    대신 변수를 하나 추가해준다.
    상태를 업데이트 하는 대신 이 변수의 값을 동적으로 계산한다.

    용어

    제어 컴포넌트 vs 비제어 컴포넌트

    presentational component vs stateful component
    상태 컴포넌트 vs 비상태 컴포넌트
    dumb component vs smart component

    일반적인 리액트 앱의 경우 전자가 후자보다 많다.

    상태는 몇 개 컴포넌트에서만 관리하고 그 상태를 다른 여러 컴포넌트에 전달하는 패턴

    'Frontend > React' 카테고리의 다른 글

    [React] section 11_1  (0) 2023.11.02
    [React] section 9, 10  (0) 2023.11.01
    [React] section 6, 7  (0) 2023.10.31
    [React] section 3  (0) 2023.10.30
    [React] section 1, 2  (0) 2023.10.30
Designed by Tistory.