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>
'Language > React' 카테고리의 다른 글
Next.js 프로젝트 파일 구조 분석 (0) | 2025.01.10 |
---|---|
[React] 예시 9. 이전 작업 node.js 환경 세팅 (0) | 2024.06.04 |
[React] 예시 7. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검사 후 local storage 값 가져오기 [리팩토링] (0) | 2024.06.03 |
[React] 예시 6. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검사 후 local storage 값 가져오기 (0) | 2024.06.03 |
[React] 예시 5. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 후 유효성 검사 (1) | 2024.06.03 |
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>
'Language > React' 카테고리의 다른 글
Next.js 프로젝트 파일 구조 분석 (0) | 2025.01.10 |
---|---|
[React] 예시 9. 이전 작업 node.js 환경 세팅 (0) | 2024.06.04 |
[React] 예시 7. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검사 후 local storage 값 가져오기 [리팩토링] (0) | 2024.06.03 |
[React] 예시 6. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 와 유효성 검사 후 local storage 값 가져오기 (0) | 2024.06.03 |
[React] 예시 5. 순수한 자바스크립트 페이지를 리액트 component 로 바꾸고, 기능 추가 후 유효성 검사 (1) | 2024.06.03 |