https://print-blue.tistory.com/191

 

[React] 예시 1. 순수한 자바스크립트 페이지를 리액트 JSX 문법으로 바꾸기

1. 자바스크립트로 구현# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능 1. 좋아요 버튼 클릭시 하트 색 변경&이미지 추가된 모습 2. 자바스크립트를 리액트 JSX 문법으로 변

print-blue.tistory.com

https://print-blue.tistory.com/193

 

[React] 예시 2. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸기

https://print-blue.tistory.com/191 [JavaScript ] 예시 1. 순수한 자바스크립트 페이지# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능 1. 좋아요 버튼 클릭시 하트 색 변경&이미지 추가

print-blue.tistory.com

https://print-blue.tistory.com/194

 

[React] 예시 3. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가(이벤트 설정)

https://print-blue.tistory.com/191 [JavaScript ] 예시 1. 순수한 자바스크립트 페이지# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능 1. 좋아요 버튼 클릭시 하트 색 변경&이미지 추가

print-blue.tistory.com

https://print-blue.tistory.com/195

 

[React] 예시 4. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가하기(상태 설정

https://print-blue.tistory.com/191 [JavaScript ] 예시 1. 순수한 자바스크립트 페이지# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능 1. 좋아요 버튼 클릭시 하트 색 변경&이미지 추가

print-blue.tistory.com

https://print-blue.tistory.com/198

 

[React] 예시 5. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 후 유효성 검

https://print-blue.tistory.com/191  [React] 예시 1. 순수한 자바스크립트 페이지를 리액트 JSX 문법으로 바꾸기1. 자바스크립트로 구현# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능

print-blue.tistory.com

https://print-blue.tistory.com/200

 

[React] 예시 5. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검

https://print-blue.tistory.com/191 [React] 예시 1. 순수한 자바스크립트 페이지를 리액트 JSX 문법으로 바꾸기1. 자바스크립트로 구현# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능

print-blue.tistory.com

https://print-blue.tistory.com/201

 

[React] 예시 7. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검

https://print-blue.tistory.com/191 [React] 예시 1. 순수한 자바스크립트 페이지를 리액트 JSX 문법으로 바꾸기1. 자바스크립트로 구현# p240530/react/ex01-javascript.html 상품 1 페이지 추가 🤍  기본 페이지기능

print-blue.tistory.com

 

이번 포스팅에서는 좋아요 클릭시 좋아요 횟수를 보여지게 할 거임 !

근데 하트 관련된 함수는 이미 정의가 되어 있으니 다시 재정의(추가) 해주자 !

 

 App

이것도 상태가 변하고 있으니까 상태값 설정해주자 !

// 좋아요 버튼 상태값
const [heartCounter, setHeartCounter] = ReactDOM.useState(0);

function handlerHeartClick() {
    setHeartCounter(heartCounter + 1);

    setFavorites((pre) => {
      const nextFavorites = [...pre, foodTree];
      jsonLocalStorage.setItem('favorites', nextFavorites);
      return nextFavorites;
    });
}

return (
    <div>
      <H1>{counter}</H1>
      <Form updateCounter={updateCounter} />
      <MainCard
        img="img/food-one.jpg"
        handlerHeartClick={handlerHeartClick}
        heartCounter={heartCounter}
      />
      <Favorites favorites={favorites} />
    </div>
);

 

MainCard

구조 분해 할당으로 인수를 넣어주고 있는데, 순서와 상관 없지만, 가독성 측면에서 순서 맞춰서 써주기 !

const MainCard = ({ img, handlerHeartClick, heartCounter }) => {
  return (
    <div className="main-card">
      <img
        src={img}
        alt="올리브 오일"
        width="400"
      />
      <button onClick={handlerHeartClick}>
        🤍{heartCounter}
      </button>
    </div>
  );
}

 

 

근데 0 을 보이는 건 별로 보기 안이쁘니까

1 이상만 표현하는 걸로 !

하지만 {} 안에서 if 문 사용하지 못함 ㅠ

or 연산자 기억나남 ! 이번엔 and 연산자를 써보자

const MainCard = ({ img, handlerHeartClick, heartCounter }) => {
  return (
    <div className="main-card">
      <img
        src={img}
        alt="올리브 오일"
        width="400"
      />
      <button onClick={handlerHeartClick}>
        🤍{heartCounter > 0 && heartCounter}
        {console.log(heartCounter)}
        {console.log(heartCounter > 0 && heartCounter)}
      </button>
    </div>
  );
}

const MainCard = ({ img, handlerHeartClick, heartCounter }) => {
      return (
        <div className="main-card">
          <img
            src={img}
            alt="올리브 오일"
            width="400"
          />
          <button onClick={handlerHeartClick}>
            🤍{heartCounter > 0 && heartCounter}
          </button>
        </div>
      );
}

 

근데 콘솔창 보면 key 값 설정하라고 빨간색 경고창 너무 거슬리니까 설정해줄 거임 !

ul 같은 경우에는 key 값을 설정하지 않아도 react 에서 만들어주지만,

나중에 만들어지는 FoodItem 은 key 값을 설정해줘야 한다.

index 로 설정하게 된다면 중복될 수 있어서 권장하지는 않지만, 지금은 그냥 패스 (관련된 라이브러리는 있는데 시간이 없으니까 패스)

const Favorites = ({ favorites }) => {
  return (
    <ul className="favorites">
      {favorites.map((food, index) => (<FoodItem img={food} key={index} />))}
    </ul>
  );
}

 

지금 문제점은 새로 고침 했을 때 좋아요 숫자가 사라지는거임 !

수업에서는 그냥 넘어가길래 내가 구현해냄 ㅎ

 

# 이전 코드
function handlerHeartClick() {
    setHeartCounter(heartCounter + 1);
    setFavorites((pre) => {
      const nextFavorites = [...pre, foodTree];
      jsonLocalStorage.setItem('favorites', nextFavorites);
      return nextFavorites;
    });
}
# 수정 코드
function handlerHeartClick() {
    setHeartCounter((pre) => {
      const nextHeart = pre + 1;
      jsonLocalStorage.setItem('heartCounter', nextHeart);
      return nextHeart;
    });

    setFavorites((pre) => {
      const nextFavorites = [...pre, foodTree];
      jsonLocalStorage.setItem('favorites', nextFavorites);
      return nextFavorites;
    });
}

 

전체 코드

<script type="text/babel">
    const jsonLocalStorage = {
      setItem: (key, value) => {
        localStorage.setItem(key, JSON.stringify(value));
      },
      getItem: (key) => {
        return JSON.parse(localStorage.getItem(key));
      },
    }

    /* component */
    const H1 = (props) => {
      return <h1>상품 {props.children} 페이지</h1>
    }
    /* component */
    const Form = ({ updateCounter }) => {
      const [value, setValue] = React.useState('');
      const [errorMsg, setErrorMsg] = React.useState('');

      const hangul = (text) => /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/.test(text);

      function handlerInputChange(data) {
        const userValue = data.target.value;
        setValue(userValue.toUpperCase());

        if (hangul(userValue)) {
          setErrorMsg('한글은 입력할 수 없습니다.');
        } else {
          setErrorMsg('');
        }
      }

      function handlerFormSubmit(event) {
        event.preventDefault();
        if (value === '') {
          setErrorMsg('빈 값은 추가 할 수 없습니다.');
          return;
        }
        updateCounter();
      }

      return (
        <form action="" onSubmit={handlerFormSubmit}>
          <input
            type="text"
            name="name"
            placeholder="상품명을 입력하세요"
            onChange={handlerInputChange}
            value={value}
          />
          <button type="submit">추가</button>
          <p style={{ color: '#f00' }}>{errorMsg}</p>
        </form>
      );
    }
    /* component */
    // 순서와 상관 없지만, 가독성 측면에서 순서 맞춰서 쓰기 !
    const MainCard = ({ img, handlerHeartClick, heartCounter }) => {
      return (
        <div className="main-card">
          <img
            src={img}
            alt="올리브 오일"
            width="400"
          />
          <button onClick={handlerHeartClick}>
            🤍{heartCounter > 0 && heartCounter}
            {/* console.log(heartCounter) */}
            {/* console.log(heartCounter > 0 && heartCounter) */}
          </button>
        </div>
      );
    }
    /* component */
    const FoodItem = ({ img }) => {
      return (
        <li>
          <img
            src={img}
            alt="음식"
            style={{ width: '150px', height: '100px', backgroundSize: 'contain' }}
          />
        </li>
      );
    }
    /* component */
    const Favorites = ({ favorites }) => {
      return (
        // 이렇게 만들어준 것은 key 값은 설정 안해줘도 react 에서 만들어주지만,
        <ul className="favorites">
          { /* 이렇게 나중에 만들어주는 것은 key 값을 설정 해줘야 함 */ }
          { /* index 로 설정하면 중복될 수 있어서 index 는 권장하지 않지만, 지금은 패스 (관련된 라이브러리 있음) */ }
          {favorites.map((food, index) => (<FoodItem img={food} key={index} />))}
        </ul>
      );
    }
    /* component : 상태 끌어올리기(lifting state up) */
    const App = () => {
      const foodOne = "img/food-one.jpg";
      const foodTwo = "img/food-two.jpg";
      const foodTree = "img/food-three.jpg";

      // 보여지는 이미지 상태값
      const [favorites, setFavorites] = React.useState(() => {
        // 초기값 빈 배열로 설정
        return jsonLocalStorage.getItem('favorites') || [];
      });
      // 페이지수 상태값
      const [counter, setCounter] = React.useState(() => {
        return jsonLocalStorage.getItem('counter');
      }
      );
      // 좋아요 버튼 상태값
      const [heartCounter, setHeartCounter] = React.useState(0);
      // const [heartCounter, setHeartCounter] = React.useState(() => {
      //   return jsonLocalStorage.getItem('heartCounter');
      // });

      function updateCounter() {
        setCounter((pre) => {
          const nextCounter = pre + 1;
          jsonLocalStorage.setItem('counter', nextCounter);
          return nextCounter;
        });
      }

      function handlerHeartClick() {
        setHeartCounter((pre) => {
          const nextHeart = pre + 1;
          jsonLocalStorage.setItem('heartCounter', nextHeart);
          return nextHeart;
        });

        setFavorites((pre) => {
          const nextFavorites = [...pre, foodTree];
          jsonLocalStorage.setItem('favorites', nextFavorites);
          return nextFavorites;
        });
      }

      return (
        <div>
          <H1>{counter}</H1>
          <Form updateCounter={updateCounter} />
          <MainCard
            img="img/food-one.jpg"
            handlerHeartClick={handlerHeartClick}
            heartCounter={heartCounter}
          />
          <Favorites favorites={favorites} />
        </div>
      );
    }

    const foodLiInsert = document.querySelector('#food-li-insert');
    ReactDOM.createRoot(foodLiInsert).render(<App />);
</script>