[간단 일기장] React에서 리스트 데이터 추가하기

미아·2023년 1월 3일
0

REACT

목록 보기
14/41

컴포넌트 트리 그려서 생각하기


-> 같은 계층끼리는 데이터 못전달해줌
🙋‍♀️그럼 어떻게 전달?

부모에 hook 만들어두고 자식요소들이 쓰게!

state끌어올리기, 역방향 event흐름, 단방향 data흐름

useRef

=> 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)을 받으며(얘네들은 작성자들이 입력해서, 바뀌어야할 데이터들이므로 받는것임!(호출할때 전달해줘야하므로)

  • 추가적으로 created_data 생성,id (useRef이용)추가한뒤
    6) setData함수 이용해서 바뀌어진 데이터를 newItem이 위로 올라오게하고 나머지 데이터를 뿌려준다.
    7) 호출은 DiaryEditor의 조건 충족하는곳에서 !
    8) 저장성공되면, 초괴화할 setState함수까지 작성해주면 끝

App.js

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;

DiaryEditor.js

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;
profile
새로운 것은 언제나 재밌어 🎶

0개의 댓글