React 완벽 가이드 - 섹션4 : 리액트 State 및 이벤트 다루기

오구·2022년 6월 12일
0

React

목록 보기
6/7
post-thumbnail

what we learn... 🖊
이벤트 핸들러 작동 방법, 핸들러 추가
state의 조정과 변환



1) Event Listening 및 Event Handler 수행

  • 모든 이벤트 관련 props들은 접두사가 'on'이다

# 이벤트를 추가하는 방법

// button tag 내 inline으로 작성한 방식
<button onClick={() => { console.log("clicked!") }}>Change Title</button>
// function을 따로 작성하여 지정한 경우
const onButtonClick = () => {
    console.log("clicked!");
}

<button onClick={onButtonClick}>Change Title</button>



2) State

  • 리액트는 응용프로그램이 처음 렌더링되었을 때 모든 과정을 실행함
    => 화면의 특정 컴포넌트들을 변경하기 위해서는 state가 필요함

# named import

  • 리액트 라이브러리에서 필요한 일부 라이브러리만 임포트하는 것
import { useState } from 'react';

# useState

  • 컴포넌트 함수가 다시 호출되는 곳에서 변경된 값을 반영하기 위해 state로 값을 정의할 수 있게 해주는 함수 (( 리액트 훅 ))
  • 사용방법 : 컴포넌트 함수 내에서 useState함수를 호출
// 변수에 접근할 수 있게 해줌. (새로운 값을 할당하기 위해 호출할 수 있는 함수도 반환
const [title, setTitle] = useState(props.title); // [현재 상태값, 값 업데이트용 함수]


const onButtonClick = () => {
    setTitle('Updated!'); // state를 업데이트하는 함수를 호출
}

  • useState는 항상 두 개의 요소가 있는 배열을 반환하며, 각 컴포넌트의 인스턴스별로 나누어져 있음
  • useState의 실행 절차 : state를 관장하는 컴포넌트 함수 호출 > 컴포넌트 재평가 > react가 컴포넌트함수 재실행 > JSX코드 재평가 > 업데이트된 값 화면 내 출력



3) 입력값 추가하기

1️⃣ form tag를 이용하여 입력값을 받을 수 있는 컴포넌트 추가

2️⃣ onChange와 useState를 통해 이벤트 구현

const ExpenseForm = () => {
	
  	// event.target.value가 String이라 ''로 초기화
    const [enteredTitle, setEnteredTitle] = useState('');
    const [enteredAmount, setEnteredAmount] = useState('');
    const [enteredDate, setEnteredDate] = useState('');

    const onTitleChange = (event) => {
        setEnteredTitle(event.target.value);
    };

    const onAmountChange = (event) => {
        setEnteredAmount(event.target.value);
    };

    const onDateChange = (event) => {
        setEnteredDate(event.target.value);
    };

3️⃣ 여러번 선언되어있는 useState를 한 번으로 압축하기

// 여러번 선언했던 state를 한 번에 정리하기
const [userInput, setUserInput] = useState({
    enteredTitle : '',
    enteredAmount : '',
    enteredDate : ''
});

const onTitleChange = (event) => {
    // 해당 키를 가진 값만 변경되기 때문에 다른 값들이 유실될 수 있으므로 스프레드 연산자(...)를 사용하여 객체를 복사 후 변경 값 오버라이드
    setUserInput({
        ...userInput,
        enteredTitle : event.target.value
    });
};

// amount, date에도 동일 적용

4️⃣ 대체 폼을 이용하여 상태 업데이트

// 이전 state의 값을 보냄
setUserInput((prevState) => {
    return { ...prevState, enteredTitle : event.target.value };
});
  • 동시적으로 많은 컴포넌트의 상태 업데이트를 해야하는 경우, 잘못된 상태값을 불러올 수 있으므로 상단과 같은 접근법을 사용하여 항상 최신 상태의 값으로 작업하도록 함

5️⃣ form submit 후 기입력값 제거

// 태그에 value값 추가
<input type='text' value={enteredTitle} onChange={onTitleChange}/>
  
// form submit내에서 State함수를 호출해 값 초기화
const onFormSubmit = (event) => {
    // 브라우저 기본 동작으로 submit 시 화면이 재로드됨
    event.preventDefault();

    setEnteredTitle('');
    setEnteredAmount('');
    setEnteredDate('');
};  



4) 컴포넌트간 통신 (자식-부모)

  • 속성은 부모에서 자식으로만 전달이 가능 (중간생략 X)
  • NewExpense(부모)에서 onSaveExpenseData(속성)를 통해 ExpenseForm(자식)에게 expenseData(인자값) 을 전달할 수 있으며,
    자식은 상수를 통해 인자값을 전달받아서 매개변수로 활용할 수 있음
// 부모 js코드 (NewExpense.js)
<ExpenseForm onSaveExpenseData={fncSaveExpenseData} />

const fncSaveExpenseData = (enteredExpenseData) => {
	// 자식에게 넘겨줄 props
  	const expenseData = {
		...enteredExpenseData,
      	id : Math.random().toString()
	};
}

// 자식 js코드 (ExpenseForm)
// props가 추가됨
const ExpenseForm = (props) => {
	// 코드생략
} 
const onFormSubmit = (event) => {

  // 코드생략
	const expenseData = {
		title : enteredTitle,
		amount : enteredAmount,
		date : new Date(enteredDate)
	};

	// 부모가 onSaveExpenseData호출 시 expenseData를 전달 할 수 있음
	props.onSaveExpenseData(expenseData);
}

⌨️ onSaveExpenseData 실행결과


⌨️ 동일 동작을 App.js - NewExpense.js에 적용 후 콘솔 확인 시



5) Lifting State Up (상태 끌어올리기)

  • 자식 컴포넌트에서 부모 컴포넌트로 데이터를 이동해 사용하거나 다른 자식 컴포넌트로 데이터를 전달하는 것
  • 현재 상태 끌어올리기 과정 : ExpenseForm.js > NewExpense.js > App.js



6) 다양한 컴포넌트

  • presentational, Stateful component, Stateless component ...
    => 다양한 컴포넌트 존재
  • presentational component : 단순히 데이터를 출력하기위해 존재하는 컴포넌트
  • stateful component : state를 사용하는 컴포넌트
  • stateless component : state를 사용하지 않는 컴포넌트
    🖊 Stateless 컴포넌트를 함수형 컴포넌트로 구현하는게 일반적인 패턴이며, Stateless 컴포넌트로 작성할 수 있다면 최대한 state를 사용하지 않도록해야 유지보수가 용이해짐
    ( 출처 : https://ibocon.tistory.com/189 )



Section4 마무리 ⌨️

  • 이벤트 핸들러가 없어 불편했던 지난날들은 빠이...지만 useState를 통해 돔객체를 다시 그리는 방식은 현재 재직중인 회사의 특정 메서드..(redraw)와 같아 신기했다.
  • 혼자 마무리겸 소스코드를 보다가 부모 소스에서 컴포넌트 속성으로 이벤트 생성할 때 자식 소스에서 동일한 이벤트 명으로 function을 생성해도 되나 테스트해봤는데 된다(!)
    여러개의 함수명을 만드는게 버거워 혹시나 싶어 도전해봤는데 되니.. 만족스럽다. props에 종속여부로 판별하는거겠지만서도 된다니 행복지수가 높아졌습니다. 짜잔
  • state는 각 value별로 관리하는게 조금 더 용이해보인다. 둘 다 상관없다고는 했지만서도 여러개를 한 번에 쓰려면 스프레드 연산자를 써야하며, 좋든 싫든 그만큼의 버퍼를 써야한다고 판단했기 때문에.. 코드가 길어져도 일단은 따로 써보는 식으로 실습을 진행하려고 한다.

결론적으로 뭐,, 이젠 다음파트인 동적생성에 목말라있다.

0개의 댓글