-
React 002-1 State,EventReact/React 2023 2023. 1. 2. 11:37728x90
그동안 정적인 어플리케이션은 만들었다 이제는 상호작용하는 동적인 애플리케이션을 만들어보자!
이벤트 리스닝, 이벤트 핸들러
모든 on props 즉 모든 이벤트 핸들러 props는 값으로 함수가 필요하고 이런 on props에 전달된 함수는 이벤트가 발생했을 때 실행되너야 한다.
... const ExpenseItem=(props)=> { const clickHandler=()=>{ console.log('Clicked!!') } return ( ... <button onClick={clickHandler}>Change Title</button> ...
이벤트 이름을 지을 때 이벤트에서 트리거 퇴고 핸들러로 끝나게 만드는 게 좋다. clickHandler
State
state는 리액트에만 특화된 것은 아니지만 리액트에서 아주 중요한 개념이다.
useState를 임포트 해준다. useState는 가장 중요한 리액트 훅 중의 하나 (훅들은 이름이 use로 시작해서 쉽게 알아낼 수 있다) 컴포넌트 함수 안에서 호출되어야 한다.
- useState는 항상 두 개의 요소가 있는 배열을 반환하는데 첫번째 요소[title]는 현재 상태값이고 두번짜 요소[setTitle]는 그것을 업데이트 하는 함수이다.
const ExpenseItem=(props)=> { const [title, setTitle] = useState(props.title); const clickHandler=()=>{ setTitle('Updated!'); console.log(title); /** * 이 함수를 호출하는 것은 어떤 변수에 새로운 값을 할당하는 것이 아니라 이 특별한 변수로 시작한다. * 이 특별한 변수는 새로운 값만 받는 것이 아니라 state를 업데이트 하는 함수를 호출하게 되고 * useState로 상태를 초기화 했던 곳에서 다시 실행될 것이다. * state가 변할 때 이 컴포넌트 함수를 다시 호출하고 싶으면 이 state를 업데이트하는 함수를 호출하면된다. */ }
useState는 몇몇 state를 등록한다. useState는 특정 컴포넌트의 인스턴스를 위해 state를 등록한다. 같은 기능을 가진 컴포넌트를 수정해도 그 하나에만 영향을 주지 다른 컴포넌트에는 영향을 주지 않는다.
const를 사용하는 이유?
state를 업데이트하는 함수를 호출하고 구체적은 값은 리액트에 의해 관리된다. 그래서 ustState를 호출해서 리액트에게 어떤 값ㅅ을 관리해야한다고 선언하는 것 그리고 stat가 업데이트 되면 재 실행 되는 것
쉽게 말해
나 "야 리액트, 내가 저번에 관리하라고 했던 최신 제목상태를 줘"
라고 명령하고
리액트는ustState가 반환하는 배열 [title, setTitle] 에서 가장 최신의 상태를 우리에게 제공하는 것이다.
useState 가 작동하는 방식
- useState를 사용해서 상태를 등록한다.
- 항상[현재 상태값, 업데이트하는함수] 두개의 값을 갖는다
- state가 변할 때 마다 업데이트 함수를 호출한다.
- JSX코드에서 출력하기 위해 상태값을 사용하고 싶을 때 마다 첫번째 요소 [현재상태값]을 사용한다.
- 리액트가 작업을 한다.
- 상태가 변할때마다 컴포넌트형 함수를 다시 실행하고
- JSX코드를 다시 평가한다.
state는 응용프로그램에게 반응성을 추가하기 때문에 아주 중요하다.
Input추가하기
출력하는 컴포넌트들을 관리하는 폴더들을 만들었는데 이제는 입력하는 컴포넌트가 들어갈 폴더를 만들어보자
대강의 폼을 준 ExpenseForm.js
import React from'react'; const ExpenseForm=()=>{ return <form action=""> <div className="new-expense__controls"> <div className="new-expense__control"> <label>Title</label> <input type="text" /> </div> <div className="new-expense__control"> <label>Amount</label> <input type="number" min="0.01" stop="0.01" /> </div> <div className="new-expense__control"> <label>Date</label> <input type="date" min="2019-01-01" max="2022-12-31" /> </div> </div> <div className="new-expense__actions"> <button type="submit">Add Expense</button> </div> </form> }; export default ExpenseForm;
NewExpense.js에서 ExpenseForm.js를 임포트해주고 App.js에다 NeweExpense.js까지 임포트 해준다.
//NewExpense.js import React from'react'; import ExpenseForm from './ExpenseForm'; import './NewExpense.css' const NewExpense=()=>{ return <div className="new-expense"> <ExpenseForm /> </div> }; export default NewExpense; ------------------------------------ //App.js import React from'react'; import ReactDOM from'react-dom'; import Expenses from "./components/Expenses/Expenses"; import NewExpense from './components/NewExpense/NewExpense'; ... return ( <div> <NewExpense /> <Expenses item={expenses} /> </div> ); } export default App;
나왔군요
아 css 임포트 깜빡했다 css임포트까지 해주면 잘 나온다 사용자 입력 리스닝
이제 사용자가 입력하는 데이터를 모아주자. 리스너를 추가해서 사용자의 요청을 들을 수 있게 해주기
... const ExpenseForm=()=>{ const titleChangeHandler=(event)=>{ console.log(event.target.value); }; return <form action=""> <div className="new-expense__controls"> <div className="new-expense__control"> <label>Title</label> <input type="text" onChange={titleChangeHandler} /> </div> ...
- titleChangeHandler라는 함수를 만들어주고 인자로 event를 잡아주면 어떤일이 일어나는지 알 수 있다.
- 확인을 위해 콘솔로 value가 어떻게 찍히는지 보고
- JSX input에 onChange를 주고 방금 만든 titleChangeHandler로 인자를 준다.
- input에 변화가 생길때마다 콘솔에 변화가 된 값이 찍히게 된다.
여러 State 다루기
이제 그거로 무엇을 할 수 있을까? 나중에 폼이 제출되었을 때 입력값들을 모아 객체에 전달해야한다.
import React, {useState} from'react'; import './ExpenseForm.css' const ExpenseForm=()=>{ const [enteredTitle, setEnteredTitle]=useState(''); const [enteredAmount, setEnteredAmount]=useState(''); const [enteredDate, setEnteredDate]=useState(''); const titleChangeHandler=(event)=>{ setEnteredTitle(event.target.value); }; const amountChangeHandler=(event)=>{ setEnteredAmount(event.target.value); }; const dateChangeHandler=(event)=>{ setEnteredDate(event.target.value); }; ...
다른 방식으로 State사용하기
useState를 한번만 뿌려주는 방법
import React, {useState} from'react'; import './ExpenseForm.css' const ExpenseForm=()=>{ // const [enteredTitle, setEnteredTitle]=useState(''); // const [enteredAmount, setEnteredAmount]=useState(''); // const [enteredDate, setEnteredDate]=useState(''); const[userInput,setUserInput] = useState({ enteredTitle:'', enteredAmount:'', enteredDate:'' }); const titleChangeHandler=(event)=>{ // setEnteredTitle(event.target.value); setUserInput({ ...userInput, //다른 데이터들이 사라지지 않도록 enteredTitle:event.target.value, }) }; const amountChangeHandler=(event)=>{ setUserInput({ ...userInput, //다른 데이터들이 사라지지 않도록 enteredAmount:event.target.value, }) }; const dateChangeHandler=(event)=>{ setUserInput({ ...userInput, //다른 데이터들이 사라지지 않도록 enteredDate:event.target.value, }) };
근데 특정 상태에서 실패할 수 도 있는 방법이라고 한다. 이전 state에 의존하는게 아니라 상태를 업데이트 하는 폼을 사용해주어야한다. 항상 업데이트가 될 수 있다는 것을 인지하게 해주는 것
const titleChangeHandler = (event) => { setUserInput((prevState) => { return { ...prevState, enteredTitle: event.target.value, }; }); }
근데 여기선 일단 첫 방법으로 진행할거다 돌아가 주자
폼 제출
버튼이 눌렸을 때 이 state들을 객체로 결합하고 싶다.
... const submitHandler = (event) => { //이벤트 객체를 다시 얻는다. event.preventDefault();//내장 자바스크립트 기본요청이 전달되는걸 막을 수 있다. const expenseData = { title:enteredTitle, amount:enteredAmount, date:new Date(enteredDate), }; console.log(expenseData); }; return ( <form onSubmit={submitHandler}> ...
양방향 바인딩 추가
입력된 것들을 어떻게 없앨 수 있지?
state를 사용하면 양방향 바인딩을 할 수 있다. 변경되는 입력값만 바꾸는 것이 아니라 입력에 새로운 값을 다시 전달 할 수 도 있는 것 이다. 프로그램에 따라 입력값을 재 설정 할 수 있는 것
간단하게 value를 설정해 주면 된다.
무한루프 같지만 정상작동한다. ... console.log(expenseData); setEnteredTitle(''); //폼이 전송되고 입력했던 걸 오버라이드해서 깨끗하게 정리 setEnteredAmount(''); setEnteredDate(''); }; return ( ...
다시 빈칸으로 돌아온다.
자식 대 부모 컴포넌트 통신(상향식)
이제ExpenseForm에는 정확하게는 App.js에는 데이터가 필요없다 데이터를 받아주기만 하면 되니까..
ExpenseForm에서 받은 데이터를 어떻게 App.js로 보낼 수 있을까?
- ExpenseForm에서 NewExpense로 보내기
- NewExpense에 속성을 추가해 준다.
- 맞춰서 함수도 작성한다.
import React from "react"; import ExpenseForm from "./ExpenseForm"; import "./NewExpense.css"; const NewExpense = () => { const onSaveExpenseData = (enteredExpenseData)=>{ const expenseData={ ...enteredExpenseData, id:Math.random().toString() }; console.log(expenseData); }; return ( <div className="new-expense"> <ExpenseForm onSaveExpenseData={onSaveExpenseData} /> </div> ); }; export default NewExpense;
- NewExpense에서 App.js로 보내기
... const addExpenseHandler = expense => { console.log('In App.js'); console.log(expense); } return ( <div> <NewExpense onAddExpense={addExpenseHandler} /> <Expenses item={expenses} /> </div> ); } ...
728x90'React > React 2023' 카테고리의 다른 글
Vue 3-1 웹팩 사용하기 (1) 2023.02.06 React001-3 리액트 기초 및 연습 (0) 2022.12.31 React 001-2 리액트에 많이 사용되는 자바스크립트 (0) 2022.12.31 React 001-1 리액트란? (1) 2022.12.31 React 000 (0) 2022.12.30