-> 같은 계층끼리는 데이터 못전달해줌
🙋♀️그럼 어떻게 전달?
=> useRef는 리랜더링 하지 않는다, 컴포넌트의 속성만 조회 & 수정!
사용하는 경우
1) 컴포넌트에 focus 위치시킬 필요가 있는 경우 (선택하고 싶은 dom에 속성으로 ref 값 설정해줌
2) 속성값 초기화 할 필요 있는 경우
3) id값줄때
1) 부모컴포넌트인 app.js에서 DiaryEditor, DiaryList가 함께 사용할 data를 가지고 있음!(useState사용)
2) DiaryList한테는 현재 데이터의 state만 넘겨주면됨! (여기선 data state)
3) 사용자가 일기를 작성하면 -> 일기리스트가 밑에서 반영되어서 떠야함! (이런식으로 바뀌는 데이터는? setState함수 써서 바뀐 데이터 반영해줘야함)
4) 바뀐 데이터 반영하고, 새로운 데이터를 위로 저장하게 할 onCreate 함수를 새롭게 만들어줌
5) onCreate함수에는 매개변수로 받아올 데이터(author, content, emotion)을 받으며(얘네들은 작성자들이 입력해서, 바뀌어야할 데이터들이므로 받는것임!(호출할때 전달해줘야하므로)
import { useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
function App() {
//1️⃣더미데이터 지우고, app(부모컴포넌트)에서 받을 usestate hook 만들기!
const [data, setData] = useState([]); // 빈배열로 출발함, 왜냐면 일기 없는 상태로 출발!
//5️⃣ useRef() 담는 변수 생성
const dataId = useRef(0);
//2️⃣onCreate라는 함수 만들어서 author, content, emotion 받아서 data에 업데이트 시키는 로직(setData이용)
const onCreate = (author, content, emotion) => {
const created_date = new Date().getTime(); // dummylist만들었던 것 처럼!
//3️⃣데이터가 추가될때마다 받을 아이들 객체로 생성!
const newItem = {
author,
content,
emotion,
#### created_date,
//4️⃣id, focus 이용할땐 useRef()이용!
id: dataId.current, // 이러면 현재
};
dataId.current += 1; // 6️⃣하나씩 올려줘야!
setData([newItem, ...data]); //7️⃣...data는 지금까지의 데이터 뿌려주기 , newItem이 가장 위로 와야하므로 먼저 위치!
};
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<DiaryList diaryList={data} />
{/* prop으로 전달함!(부모=> 자식컴포넌트로 데이터 전달!) */}
</div>
);
}
export default App;
import React, { useRef, useState } from "react";
const DiaryEditor = ({ onCreate }) => {
const authorInput = useRef(); // useRef() 함수는, mutableobject는 dom요소 접근할수있는 객체를 반환함
const contentInput = useRef();
const [state, setState] = useState({
author: "",
content: "",
emotion: 1,
});
//목적: onChange에 목적이 같은 코드 중복
const handlerChangeState = (e) => {
// console.log(e.target.name);
// console.log(e.target.value);
//name을 우리가 author / content 즉, 초기값 키의 이름과 일치시켜놨으니 사용가능!
setState({
...state, //spread로 전체 펼쳐주고
[e.target.name]: e.target.value,
});
};
//목적: button 클릭할때마다 submit 되게
const handleSubmit = () => {
if (state.author.length < 1) {
authorInput.current.focus();
return; // 더이상 진행이 안되게
}
if (state.content.length < 5) {
contentInput.current.focus();
return;
}
onCreate(state.author, state.content, state.emotion); //onCreate 함수에 매개변수 담아서 호출!(onCreate는 app.js에 존재)
console.log(state); // 조건 만족하면, 콘솔에 찍어주는 상태
alert("저장 성공!");
//그리고 DiaryEditor가 비워져있어야하므로
setState({
author: "",
content: "",
emotion: 1, //초기화
});
};
// setState는 상태를 바꿔주는 함수이기때문에 여기에 접근할 수는 없음,
// 값을 확인하려면 state.author 해서 접근해야함
return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
ref={authorInput}
value={state.author} //state만 써주면 객체만 들어감
name="author" //input에서의 name은 데이터 넘길때 넘어가는애~
onChange={handlerChangeState}
/>
</div>
<div>
<textarea
ref={contentInput}
name="content"
placeholder="일기의 내용을 입력해주세요"
value={state.content}
onChange={handlerChangeState}
/>
</div>
<div>
<span>오늘의 감정점수:</span>
<select
name="emotion"
value={state.emotion}
onChange={handlerChangeState}
>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
</div>
<div>
<button onClick={handleSubmit}>일기 저장하기</button>
</div>
</div>
);
};
export default DiaryEditor;