//log my lifestyle

[React] 💻 react완벽가이드(4) 본문

Web/React

[React] 💻 react완벽가이드(4)

zici 2022. 5. 12. 04:28

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

 


1. 이벤트 핸들러 써보기

const ExpenseItem =(props) => {
  function clickHandler(){ } // 함수로 쓰거나
  
  const clickHandler = () => { // 화살표함수로 쓰거나 상관없음
    console.log('clicked!')
  }
  return (
      <button onClick={clickHandler}>Change Title</button>
  );
}

이벤트리스너를 추가할때 on으로 시작하는 props를 괄호안에 함수이름만 적어주면 된다.

함수이름뒤에 괄호를 추가하면  jsx코드가 리턴될때 코드가 실행된다. 그래서 함수만 지정하고 onClick을 위한 값으로 이 포인터를 전달하고 클릭할때 함수를 실행!

 

2. State 

컴포넌트 함수는 처음 렌더링 된 이후로 다시 호출되지않는다. 어떤 변경사항을 반영하기 위해서 리액트 라이브러리를 import해야함

import React, { useState } from 'react';

useState 는 리액트 라이브러리에서 제공하는 함수(리액트 훅이라고 불림)

컴포넌트 함수가 다시 호출되는 곳에서 변경된 값을 반영하기 위해 state로 값을 정의할 수있게 해주는 함수

 

모든 훅들은 리액트 컴포넌트 함수안에서 직접적으로 호출되어야함 (함수밖 호출 ❌, 중첩된 함수 안 호출❌)

 

const [title, setTitle] = useState(props.title);

 useState 는 배열을 반환, 첫번째 요소는 현재상탯값을, 두번째 요소로 그값을 업데이트되는 함수를 리턴한다.

배열구조분해를 사용해서 각각을 변수(또는 상수)로 담을수 있다.

 

const ExpenseItem =(props) => {
  const [title, setTitle] = useState(props.title);

  const clickHandler = () => {
    setTitle('Updated!');

  }
  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} />
      <div className="expense-item__description">
        <h2>{title}</h2>
        <div className="expense-item__price">${props.amount}</div>
      </div>
      <button onClick={clickHandler}>Change Title</button>
    </Card>
  );
}

state는 컴포넌트의 인스턴스별로 나뉘어져있다. 즉,컴포넌트 별 인스턴스를 기반으로 독립적인 state를 갖는다.

 

3. 사용자 입력 리스닝

import react, { useState } from 'react';

const ExpenseForm = () => {
  const [enteredTitle, setEnteredTitle] = useState('');
const titleChangeHandler = (event) => {
   setEnteredTitle(event.target.value); 
  };
  return ( 
          <input type='text' onChange={titleChangeHandler} />
 )

입력에 대해 변경이벤트를 수신할때,  입력 요소값을 읽는다면 항상 문자열로 얻게됨

 

useState 다른방식으로 쓰기

const ExpenseForm = () => {
  const[userInput,setUserInput]= useState({
    enteredTitle:'',
    enteredAmount:'',
    enteredData:'',
  })
  const titleChangeHandler = (event) => {
    setUserInput({
      ...userInput,
      enteredTitle: event.target.value,
    })
  };
 
  return (

state를 한번 호출해서 객체로 여러개 다룰수 있다.

이전방식과 차이점은 state를 업데이트를 할때마다 한개가아니라 예시의 세 프로퍼티 모두 업데이트 해야한다는점

하나의 객체에서 업데이트할때마다 이전state는 대체되고 사라질 수 있기때문에 spread연산자를 사용해서 기존값 복사하기

하지만 이 코드보단 아래코드처럼 쓰길 권장한다!

  const titleChangeHandler = (event) => {
 	//setUserInput에 전달하는 이 함수는 리액트에 의해 자동으로 실행
    setUserInput((prevState) => {
      return { ...prevState, enteredTitle: event.target.value };
    });
  };

리액트는 state update 스케쥴을 갖고 있고, 그걸 바로 실행하지 않는다.

그래서 동시에 많은 상태 업데이트를 계획할때 오래되거나 ,잘못된 상태 스냅샷에 의존할수있음

이 접근방법은 최신 상태의 스냅샷에서 작업하도록 하는좀 더 안전한 방법

 

4.양식 제출 처리

  const submitHandler = (event) => {
    event.preventDefault(); //submit시 화면이 리로드되는거 방지
    const expenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate)
    };
    console.log(expenseData);
    // 값을 저장했으면 초기화
    props.onSaveExpenseData();
    setenteredTitle('');  
    setenteredAmount('');
    setenteredDate('');
  };
  
  return ( 
    <form onSubmit={submitHandler}> //form에 submit이벤트 등록
      <div>
        <div>
          <label>title</label>
          <input
            type='text'
            value={enteredTitle} //input에서 value속성을 {enteredTitle}로 지정, 다른input에도해당값 동일처리
           />
        </div>
      </div>
   	  <button type='submit'>Add Expense</button>

state 양방향바인딩 / 변경되는 입력값만 수신하는것이 아니라 입력에 새로운 값을 다시 전달할수 있음  

 

5.자식 대 부모 컴포넌트 통신(상향식)

1.부모 컴포넌트로부터 자식 컴포넌트로 함수를 전달

2.자식 컴포넌트에서 그 함수를 호출

3.호출했을때 함수에 매개변수로 데이터를 전달

App.js
└ NewExpense.js
  └ ExPenseForm.js //expense에서 생성한 데이터를 app컴포넌트에 전달하고싶음

여기서 중간 컴포넌트 생략할 수는 없음 - 단계별로 전달해야한다.

 

const NewExpense = (props) => {
  const saveExpenseDataHandler = (enteredExpenseData) => { ///ExpenseForm에서 제출된 데이터가 매개변수로 
    const expenseData = {
      ...enteredExpenseData, //ExpenseForm에서 제출된 데이터
    };
    props.onAddExpense(expenseData);
  }
  return <div>
    <ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />  //함수자체가 ExpensForm으로전달
  </div>
};

export default NewExpense;

먼저 부모컴포넌트에서 함수를 만들고, 리턴문에 자식컴포넌트의 props 를 지정한다.

함수를 통해 포인터를 전달 -> 컴포넌트끼리 , 자식에서 부모컴포넌트로 소통하는방법

 

const ExpenseForm = (props) => { // props전달
  const submitHandler = (event) => {
    event.preventDefault();
    const expenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate),
    };
    //포인터로 전달받은 함수를 호출할수 있음, 매개변수로 데이터를 전달
    props.onSaveExpenseData(expenseData); 
    setEnteredTitle('');
    setEnteredAmount('');
    setEnteredDate('');
  };

자식 컴포넌트에서 전달받은 함수를 호출한다. 그러면 부모컴포넌트에서는 자식컴포넌트에서 저장된 배열을 받아올수있음

 

 

 

//REF.

https://www.udemy.com/course/best-react/

강의를 듣고 정리한 학습노트입니다 :)

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

[React] 💻 react완벽가이드(6)  (0) 2022.05.18
[React] 💻 react완벽가이드(5)  (0) 2022.05.16
[React] 💻 react완벽가이드(3)  (0) 2022.05.09