[React] 조건부 내용 출력

summereuna🐥·2023년 3월 16일
0

React JS

목록 보기
35/69

예제

새로운 비용 추가하기 버튼을 누르면 비용을 추가할 수 있는 폼이 뜨고, 폼에서 취소를 누르면 다시 폼은 없어지고 새로운 비용 추가하기 버튼이 생기도록 만들어 보자.

1. 상태 추가

렌더링되는 상태가 바뀌는 것이기 때문에 상태를 추가한다. 디폴트 값으로는 false를 준다.

// 📍 NewExpense.js

const [isEditing, setIsEditing] = useState(false);

2. 버튼 클릭 시 상태를 바꾸는 핸들러 설정

새로운 비용 추가 버튼을 만들고, 버튼을 클릭했을 때 상태가 변할 수 있도록 핸들러를 설정한다.

  • isEditing state를 변경하기 위한 setIsEditing()를 호출하는 startEditingHandler를 생성한다.
  • 새로운 비용 추가 버튼을 클릭onClick했을 때 startEditingHandler를 포인팅한다.
// 📍 NewExpense.js

  const startEditingHandler = () => {
    setIsEditing((prev) => !prev);
  };
//...
return(
  <div className="new-expense">
    <button onClick={startEditingHandler}>새로운 비용 추가</button>
    <ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
  </div>
);

3. 삼항연산자와 앤드연산자를 사용하여 상태 값에 따른 다른 jsx 반환

삼항연산자와 앤드연산자를 사용하여 isEditing의 true/false 값에 따른 jsx, <button> 혹은 <ExpenseForm />를 반환한다.

  • isEditing 상태가 false일 때(즉, !isEditingtrue일 때)만 새로운 비용 추가 버튼을 렌더링한다.
  • isEditing 상태가 true일 때(즉, isEditingtrue일 때)만 ExpenseForm 컴포넌트를 렌더링한다.
// 📍 NewExpense.js

return (
    <div className="new-expense">
      {!isEditing && (
        <button onClick={startEditingHandler}>새로운 비용 추가</button>
      )}
      {isEditing && (
        <ExpenseForm
          onSaveExpenseData={saveExpenseDataHandler}
        />
      )}
    </div>
  );

4. 취소 버튼 클릭시 상태 바꾸기 위한 핸들러 작성 및 props으로 하위 컴포넌트에 전달

취소버튼을 클릭하면 다시 isEditing의 상태를 바꾸도록 해야 하기 때문에 상태를 바꾸기 위한 stopEditingHandler를 생성하여 <ExpenseForm />컴포넌트에 props으로 전달한다.

// 📍 NewExpense.js

 const stopEditingHandler = () => {
    setIsEditing((prev) => !prev);
  };
//...
return (
    <div className="new-expense">
      {!isEditing && (
        <button onClick={startEditingHandler}>새로운 비용 추가</button>
      )}
      {isEditing && (
        <ExpenseForm
          //🔥
          onCancel={stopEditingHandler}
          onSaveExpenseData={saveExpenseDataHandler}
        />
      )}
    </div>
  );

5. 하위 컴포넌트에 취소 버튼 생성 및 onClick에 전달한 props 포인팅

ExpenseForm이 반환하는 jsx에 type="button"인 버튼을 추가한다.
props로 받아온 onCancel을 onClick에 포인트한다.

//📍 NewExpense.js > ExpenseForm.js

import { useState } from "react";
import "./ExpenseForm.css";

const ExpenseForm = (props) => {
  //...
  return (
    <form onSubmit={submitHandler}>
      //...
      <div className="new-expense__actions">
        //🔥
        <button type="button" onClick={props.onCancel}>
          취소
        </button>
        <button type="submit">비용 추가</button>
      </div>
    </form>
  );
};

export default ExpenseForm;

6. 새로운 비용 추가 후, 상태 변경하여 폼 닫기

마지막으로 새로운 비용을 추가한 후, isEditing 상태를 변경하여 폼을 닫아보자.

// 📍 NewExpense.js
const saveExpenseDataHandler = (enteredExpenseData) => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    //상위 컴포넌트에서 props으로 받은 함수에 저장할 data 인자로 전달
    props.onAddExpenseData(expenseData);
    //🔥 폼에 저장하고 나면 에디팅창 끄기
    setIsEditing((prev) => !prev);
  };

정리

📍 NewExpense.js

import "./NewExpense.css";
import ExpenseForm from "./ExpenseForm";
import { useState } from "react";

const NewExpense = (props) => {
  const [isEditing, setIsEditing] = useState(false);

  const saveExpenseDataHandler = (enteredExpenseData) => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    //상위 컴포넌트에서 props으로 받은 함수에 저장할 data 인자로 전달
    props.onAddExpenseData(expenseData);
    //🔥 폼에 저장하고 나면 에디팅창 끄기
    setIsEditing((prev) => !prev);
  };

  //🔥 새로운 비용 추가 버튼을 클릭했을 때 isEditing state를 변경하는 setIsEditing()를 호출한다.
  const startEditingHandler = () => {
    setIsEditing((prev) => !prev);
  };
  
  //🔥 취소 버튼을 클릭했을 때 isEditing state를 변경하는 setIsEditing()를 호출한다.
  // 이 핸들러는 onCancel props을 통해 ExpenseForm으로 전달하여 거기서 포인팅하면 된다.
  const stopEditingHandler = () => {
    setIsEditing((prev) => !prev);
  };

  return (
    <div className="new-expense">
      //🔥 삼항연산자와 앤드연산자를 사용하여 isEditing의 true/false 값에 따른 jsx를 반환한다.
      //isEditing 상태가 false일 때(즉, !isEditing가 true일 때)만 새로운 비용 추가 버튼을 렌더링한다.
      {!isEditing && (
        <button onClick={startEditingHandler}>새로운 비용 추가</button>
      )}
      //isEditing 상태가 true일 때(즉, isEditing가 true일 때)만 ExpenseForm 컴포넌트를 렌더링한다.
      {isEditing && (
        <ExpenseForm
          onCancel={stopEditingHandler}
          onSaveExpenseData={saveExpenseDataHandler}
        />
      )}{" "}
    </div>
  );
};

export default NewExpense;

📍 ExpenseForm.js

import { useState } from "react";
import "./ExpenseForm.css";

const ExpenseForm = (props) => {
  //...
  return (
    <form onSubmit={submitHandler}>
      //...
      <div className="new-expense__actions">
        //🔥
        <button type="button" onClick={props.onCancel}>
          취소
        </button>
        <button type="submit">비용 추가</button>
      </div>
    </form>
  );
};

export default ExpenseForm;
profile
Always have hope🍀 & constant passion🔥

0개의 댓글