React - 시작하기 (2. CREATE)

sarang_daddy·2023년 5월 6일
0

React

목록 보기
2/26

어플리케이션은 기본적으로 아래의 4가지 기능을 가지고 있다.

  • READ
  • CREATE
  • UPDATE
  • DELETE

앞서 학습한 리액트 시작하기READ 기능에 해당한다.
이번에는 리액트의 CREATE 기능을 학습해보자.

⛔️ 생활코딩 - 리액트 강의를 정리한 내용입니다.

CREATE 페이지 만들기

  return (
    <div className="App">
      <Header
        title="React 연습"
        onChangeMode={() => {
          setMode("WELCOME");
        }}
      ></Header>
      <Nav
        topics={topics}
        onChangeMode={(_id) => {
          setMode("READ");
          setId(_id);
        }}
      ></Nav>
      {content}
      <a 
        href="/create" // 1️⃣
        onClick={(event) => {
          event.preventDefault();
          setMode("CREATE"); // 2️⃣
        }}
      >
        Create - 새로운 항목을 생성하세요.
      </a>
    </div>
  );

1️⃣ : 새로운 항목을 만드는 페이지로 이동하기 위한 링크
2️⃣ : 리액트는 SPA프레임워크다 우리는 새로운 페이지를 생성하지 않고, 상태를 바꾸어서 해당 상태의 UI만 변경되도록 한다.

  if (mode === "WELCOME") {
    content = <Article title="Wellcome" body="Hello, React"></Article>;
  } else if (mode === "READ") {
    let title,
      body = null;

    topics.forEach((topic) => {
      if (topic.id === id) {
        title = topic.title;
        body = topic.body;
      }
    });
    content = <Article title={title} body={body}></Article>;
  } else if (mode === "CREATE") {
    content = <Create></Create>; // 3️⃣
  }

3️⃣ : 상태(mode)가 "CREATE" 일 때 content UI는 컴포넌트 Create를 따른다.

export function Create() { // 4️⃣
  return (
    <article>
      <h2>Create 페이지</h2>
      <form> // 5️⃣
        <p><input type="text" name="title" placeholder="title.."></input></p>
        <p><textarea name="body" placeholder="body.."></textarea></p>
        <p><input type="submit" value="Create!"></input></p>
      </form>
    </article>
  );
}

4️⃣ : Create 컴포넌트 생성
5️⃣ : 사용자의 input값을 전달하므로 form 태그로 작성

CREATE 입력값 가져오기

export function Create(props) // 1️⃣ {
  return (
    <article>
      <h2>Create 페이지</h2>
      <form onSubmit={(event) => { // 2️⃣
        event.preventDefault();
        const title = event.target.title.value;
        const body = event.target.body.value;
        props.onCreate(title, body) // 3️⃣
      }}>
        <p><input type="text" name="title" placeholder="title.."></input></p>
        <p><textarea name="body" placeholder="body.."></textarea></p>
        <p><input type="submit" value="Create!"></input></p>
      </form>
    </article>
  );
}

/////////////////////////

else if (mode === "CREATE") {
    content = <Create onCreate= {(_title, _body) => {

    }}></Create>;
  }

1️⃣ : CREATE 상태일 때, 사용자 입력값을 가져와서 행동할 함수를 props로 전달
2️⃣ : 사용자 입력값을 전달하기 위해 "Create!" 제출시 onSubmit 함후 실행
3️⃣ : 사용자가 입력한 값(title, body)을 props함수에 전달한다.

입력값으로 CREATE 하기

Create 컴포먼트에서 입력받은 값들로 행동(CREATE)을 취한다.

function App() {
  // 1️⃣
  const [topics, setTopics] = useState([
    { id: 1, title: "html", body: "html is..." },
    { id: 2, title: "css", body: "css is..." },
    { id: 3, title: "javaScript", body: "javaScript is..." },
  ]);
  
  // 2️⃣
  const [nextId, setNextId] = useState(4);

  ////////////////////////////////////////////////
  
  else if (mode === "CREATE") {
    content = (
      <Create
        onCreate={(_title, _body) => {
      	  // 3️⃣
          const newTopic = { id: nextId, title: _title, body: _body };
          const newTopics = [...topics]; // 4️⃣
          newTopics.push(newTopic);
          setTopics(newTopics);
        }}
      ></Create>
    );
  }

1️⃣ : 입력값으로 CREATE하고자 하는 것은 topic의 요소 추가다.
2️⃣ : 새로운 topic들의 id를 상태로 관리하기 위한 추가
3️⃣ : 입력받은 값들로 새로운 topic을 만든다.
4️⃣ : 상태 변경의 값이 범객체(object, arrat)라면 반드시 복제 후에 상태를 변경해주어야 한다.

⭐️ 상태변경으로 인한 리액트에서의 렌더링 ⭐️

리액트에서는 상태가 변경되면 (setMode등) 해당 컴포넌트를 다시 렌더링 해준다고 했다.
여기서 주의해야 할 점이 있다.

원시값이 아닌 객체의 상태 변경의 경우 리렌더링이 일어나지 않는다.

❗️ 원시값의 경우
const [value, setValue] = useState(1)
setValue(2)

-> 최초 value는 값 1이다.
-> setValue(2)로 value 값은 2가 되었다.
-> 리액트는 오리지날 값 1이 2로 변경됨을 감지하고 리렌더링 한다.

❗️ 범객체의 경우(obj, array 등)
const [value, setValue] = useState([1])
value.push(2)
setValue(value)

-> 최초 value는 [1]을 가진다.
-> value에 새로운 값 [2]를 추가하여 [1,2]가 되도록 한다.
-> [1,2]가 된 value를 setValue 해준다.
-> 리액트는 setValue(value)를 검토하지만, 오리지날 value만 검토한다.
-> 오리지날 value는 변경되지 않았기에 리렌더링이 일어나지 않는다.

객체의 상태변경의 경우 Spread 연산자를 이용하여 복제 후 값을 변경하고
변경된 복제의 객체로 상태 변경을 요청해야 한다.

💡 범객체에서의 상태변경
const [value, setValue] = useState([1])
const newValue = [...value]
newValue.push(2)
setValue(newValue)

-> newValue는 오리지날 value와 값이 다르기에 리렌더링이 일어난다.

상태관리를 통한 App조작

else if (mode === "CREATE") {
    content = (
      <Create
        onCreate={(_title, _body) => {
          const newTopic = { id: nextId, title: _title, body: _body };
          const newTopics = [...topics];
          newTopics.push(newTopic);
          setTopics(newTopics);
          setId(nextId); // 1️⃣
          setMode("READ"); // 2️⃣
          setNextId(nextId + 1); // 3️⃣
        }}
      ></Create>
    );
  }

1️⃣ : CREATE된 요소의 ID를 현재 ID로 상태변경 해준다.
2️⃣ : mode의 상태를 "READ"로 변경해주면 CREATE된 항목의 "READ"로 바로 렌더링 된다. (id를 변경해 주었으므로)
3️⃣ : 새로 CREATE될 요소를 위해 nextId값을 1증가 시켜준다.

profile
한 발자국, 한 걸음 느리더라도 하루하루 발전하는 삶을 살자.

0개의 댓글