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
이전 포스팅을 보면 새로 고침을 했을 때,
추가한 페이지와 추가한 이미지가 초기화 된다 !
이때 local storage 접근해보자 !
local storage 에 저장하기
다른 컴포넌트는 수정된 게 없어서 생략 !
App
1. 페이지 추가 후 새로 고침해도 값 그대로
App 에서 페이지 수 와 관련된 상태값 설정했다 .
updateCounter 함수에서 코드 추가해주자
function updateCounter() {
// event.preventDefault(); 기능 없어져도 됨
setCounter(counter + 1);
// loacalStorage 에 저장
loacalStorage.setItem('counter', counter);
}
근데 확인해보면 1씩 차이가 남 !
상태 변경 호출이 될 때 상태 변경 전에 값으로 유지/보장이 되기 때문에
local storage 에 저장되는 값은 상태 변경 전 값으로 저장이 됨 !!
관련 내용 (https://print-blue.tistory.com/189)
그럼 이 둘 값을 일치 시켜야 되니까
지역 변수에 넣어주자
그럼 이제 updateCounter() 호출이 끝나면 counter 가 저장이 되면서 동기화 될거임 !
function updateCounter() {
const nextCounter = counter + 1;
setCounter(nextCounter);
// local storage 에 저장
localStorage.setItem('counter', nextCounter);
}
그럼 이제 새로 고침을 해도 상품 페이지가 그대로 있게 해주자
local storage 에 저장된 값을 초기값으로 설정 !
const [counter, setCounter] = React.useState(localStorage.getItem('counter'));
했는데 또 문제 생김
아마 초기값을 문자열로 처리해서 일듯 ^-ㅠ..
확이해보면 맞음 ㅠ
const [counter, setCounter] = React.useState(localStorage.getItem('counter'));
console.log('localStorage.getItem("counter") >> ', localStorage.getItem('counter'));
console.log('typeof localStorage.getItem("counter") >> ', typeof localStorage.getItem('counter'));
Number 로 형변환 해주자
const [counter, setCounter] = React.useState(Number(localStorage.getItem('counter')));
console.log('localStorage.getItem("counter") >> ', Number(localStorage.getItem('counter')));
console.log('typeof localStorage.getItem("counter") >> ', typeof Number(localStorage.getItem('counter')));
근데 json 으로 역직렬화 해주자
const [counter, setCounter] = React.useState(JSON.parse(localStorage.getItem('counter')));
console.log(JSON.parse(localStorage.getItem('counter')));
console.log('type 확인 >> ', typeof JSON.parse(localStorage.getItem('counter')));
function updateCounter() {
const nextCounter = counter + 1;
console.log('typeof nextCounter >> ', typeof nextCounter);
// updateCounter() 가 끝나면 저장이 됨
// 동기화 됨
setCounter(nextCounter);
// local storage 에 저장
// localStorage.setItem('counter', nextCounter);
// 잘 되긴 하지만 역직렬화 해주기
localStorage.setItem('counter', JSON.stringify(nextCounter));
}
객체 형태로 관리하자 ...
const jsonLocalStorage = {
setItem : (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
},
getItem : (key) => {
// 값을 가져오는 거니까 return 이 필요함
return JSON.parse(localStorage.getItem(key));
},
}
const [counter, setCounter] = React.useState(jsonLocalStorage.getItem('counter'));
function handlerHeartClick() {
setFavorites([...favorites, foodTree]);
jsonLocalStorage.setItem('favorites', [...favorites, foodTree]);
}
2. 이미지 추가 후 새로 고침되도 값 그대로
const [favorites, setFavorites] = React.useState(jsonLocalStorage.getItem('favorites'));
Cannot read properties of null (reading 'map') ...
Favorites 로 가자 ..
const Favorites = ({ favorites }) => {
return (
<ul className="favorites">
{favorites.map(food => (<FoodItem img={food} key={food} />))}
</ul>
);
}
지금 favorites 이 null 인데 배열 형태로 지금 map 이 도니까.. !
or 연산자는 논리값이 나오는 것들은 true 또는 false 를 return 해주지만,
자바스크립트의 or 연산자는 논리값이 안나오는 값을 진짜 true 진짜 flase 는 아니지만 Boolean 을 해줘서
true 인걸로 가져오는데
둘 다 true 일 때 왼쪽 값을
둘 다 false 일 때 오른쪽 값을 가져온다
(and 연산자는 둘다 검사하고 좀 다름 ..! 공부 해라 ..)
자 다시 돌아와서
null(false) || [](true) 가 된다
// const [favorites, setFavorites] = React.useState(jsonLocalStorage.getItem('favorites'));
const [favorites, setFavorites] = React.useState(jsonLocalStorage.getItem('favorites') || []);
console.log(jsonLocalStorage.getItem('favorites') || [])
console.log(jsonLocalStorage.getItem('favorites'))
function handlerHeartClick() {
setFavorites([...favorites, foodTree]);
jsonLocalStorage.setItem('favorites', [...favorites, foodTree]);
}
그럼 이제 에러가 사라지고 ! 사진도 안보여질 것
초기값 다시 설정
const [favorites, setFavorites] = React.useState(jsonLocalStorage.getItem('favorites') || [foodOne, foodTwo]);
그럼 완성 !
전체코드
<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 }) => {
return (
<div className="main-card">
<img
src={img}
alt="올리브 오일"
width="400"
/>
<button onClick={handlerHeartClick}>🤍</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 (
<ul className="favorites">
{favorites.map(food => (<FoodItem img={food} key={food} />))}
</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(jsonLocalStorage.getItem('favorites') || [foodOne, foodTwo]);
const [counter, setCounter] = React.useState(jsonLocalStorage.getItem('counter'));
function updateCounter() {
const nextCounter = counter + 1;
setCounter(nextCounter);
jsonLocalStorage.setItem('counter', nextCounter);
}
function handlerHeartClick() {
setFavorites([...favorites, foodTree]);
jsonLocalStorage.setItem('favorites', [...favorites, foodTree]);
}
return (
<div>
<H1>{counter}</H1>
<Form updateCounter={updateCounter} />
<MainCard
img="img/food-one.jpg"
handlerHeartClick={handlerHeartClick}
/>
<Favorites favorites={favorites} />
</div>
);
}
const foodLiInsert = document.querySelector('#food-li-insert');
ReactDOM.createRoot(foodLiInsert).render(<App />);
</script>