개발 마라톤

[React] 생성, 수정, 삭제 기능 구현 본문

--- Front-end ---/React

[React] 생성, 수정, 삭제 기능 구현

망__고 2023. 1. 4. 21:37

8. Create

https://youtu.be/kctNCMFxciQ

더보기

애플리케이션은 기본적으로 Create, Read, Update, Delete의 4가지 기능을 구현한다.

state를 정의할 때 기본형이 아닌 객체를 사용할 때는 사용 방법이 달라진다.

state를 변경할때, 인자를 Object(객체)로 주고 싶다면 단순히 setValue(Object)로 변경을 할 수 없다.

 객체를 주기 위해서는 newValue = {...value} (혹은 배열은 [...value] 로 state를 복제한다.

그리고 state를 객체값으로 변경한 후, setValue(newValue)로 설정해주면 된다.

복잡한 이야기지만, 간단하게 객체를 복제 후 수정 한 다음 setValue 해주면 되는 것.

Create라는 글을 클릭하면, title과 body를 작성하여 새 topic을 추가하는 기능을 구현했다.

 

Create 컴포넌트는 form의 input과 textarea를 통해 title과 body를 onCreate로 App 컴포넌트에 넘겨준다.

topics를 state로 승격시켜서 create기능을 통해 topics를 추가시키면 App()이 렌더링 되도록 기능을 추가했다.

Create 컴포넌트 에서 title과 body를 props를 통해 전달한 후, 그 정보를 토대로 topic을 추가한다.

 

KeyWord

url이동은 없지만 href="/create"의 형식을 지키자form 태그의 event.target.___.value를 통해 내용 받아옴

객체를 쓰는 state는 복제본( {...value}, [...value] )을 수정하고 setValue

 

9. Update

https://youtu.be/bW_WOrYzVWw

더보기

Update는 Create, Read를 하이브리드해서 구현함.

UPDATE 모드를 추가한 App.js 내용 일부
Update 컴포넌트는 실행 중 변경되지 않는 props를 state로 변경 후 setValue를 통해 변경시킨다.

 Update 기능은

  1. 원래 내용을 READ 후 title과 body를 화면에 표시한다.
  2. props를 state로 변환 후 onChange의 이벤트를 통해 setValue함
  3. 그 값을 onUpdate를 통해 App 컴포넌트로 전달
  4. newTopics 수정 후 setTopics

 

KeyWord

실행 중 props 데이터는 변하지 않음

props 데이터는 state변환 후 setValue를 통해 변경

onChange 이벤트를 통해 value를 변경함

 

10. Delete

https://youtu.be/OZPRKFqPWG4

더보기
contextControl 부분만 수정

READ일때 Delete기능을 수행할 수 있도록 구현했다.

React는 한번의 수행때 한 번의 태그만 확인하므로, 태그 여러개를 다룰 때는 빈 태그 <></>로 묶는다.

Delete버튼을 누르면(onClick) 현재 topic만 제외한 다른 토픽만으로 이루어진 newTopics로 setTopics한다.

 

KeyWord

React는 하나의 태그씩 다루므로, 여러개의 태그는 빈 태그 <></>로 묶음

 

import logo from './logo.svg';
import './App.css';
import {useState} from 'react';

function Article(props){
  return <article>
    <h2>{props.title}</h2>
    {props.body}
  </article>
}

function Header(props){
  console.log('props', props, props.title);
  return <header>
    <h1><a href="/" onClick={(event)=> {
      event.preventDefault(); // reload하는 기본 이벤트를 방지
      props.onChangeMode();
    }}>{props.title}</a></h1>
  </header>
}

function Nav(props){
  const lis = []
  for(let i=0; i<props.topics.length; i++){
    let t = props.topics[i];
    lis.push(<li key={t.id}>
      <a id = {t.id} href={'/read/'+t.id} onClick={(event)=> {
      event.preventDefault();
      props.onChangeMode(Number(event.target.id)); // target은 event를 유발시킨 태그를 가르킴
    }}>{t.title}</a></li>)
  }
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>
}

function Create(props) {
  return <article>
    <h2>Create</h2>
    <form onSubmit={event=>{
      event.preventDefault();
      const title = event.target.title.value; // event.target은 이벤트를 발생시킨 form 태그를 가리킴.
                                              // 또한 그 뒤에는 name속성으로 접근한 후, 값은 value 멤버로 접근하면 된다.
      const body = event.target.body.value;
      props.onCreate(title, body);            // 정보 전달을 위한 props함수 사용.
    }}>
      <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>
}

function Update(props) {
  // props 데이터들은 이미 사용자가 정해준 값이기 때문에, 실행 중간에 바뀌지 못함
  // 그러므로 state로 변경하여 실행 중 바꿀 수 있도록함
  const [title, setTitle] = useState(props.title);
  const [body, setBody] = useState(props.body);
  return <article>
    <h2>Update</h2>
    <form onSubmit={event=>{
      event.preventDefault();
      const title = event.target.title.value; // event.target은 이벤트를 발생시킨 form 태그를 가리킴.
                                              // 또한 그 뒤에는 name속성으로 접근한 후, 값은 value 멤버로 접근하면 된다.
      const body = event.target.body.value;
      props.onUpdate(title, body);            // 정보 전달을 위한 props함수 사용.
    }}>
      <p><input type="text" name="title" placeholder="title" value={title} onChange={event=>{ // 값이 바뀔때 onChange
        setTitle(event.target.value); // props의 값은 바로 바꾸지 못하기 때문에 state로 변환 후, setValue를 통하여 변경.
      }}></input></p>
      <p><textarea name="body" placeholder="body" value={body} onChange={event=>{
        setBody(event.target.value);
      }}></textarea></p>
      <p><input type="submit" value="Update"></input></p>
    </form>
  </article>
}

function App() {
  // state는 변수의 값과 값을 변경하는 함수의 배열로 이루어져있다.
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4);  // id를 자동으로 생성
  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 ...'}
  ] )
  let content = null;
  let contextControl = null;

  if(mode === 'WELCOME') {
    content = <Article title="Welcome" body="Hello, WEB"></Article>
  } else if(mode === 'READ') {
    let title, body = null;
    for(let i =0; i<topics.length; i++)
      if(topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
      }
    content = <Article title={title} body={body}></Article>

    // READ모드일때만 Update버튼이 나타나도록 설정
    contextControl = <> 
      <li><a href={"/update"+id} onClick={event=>{
        event.preventDefault();
        setMode('UPDATE');
      }}>Update</a></li>  
      <li><input type="button" value="Delete" onClick={()=>{
        const newTopics = []
        // 현재 topic의 id(삭제할 topic)만 제외하고 새로운 topics을 만들어 적용
        for(let i=0; i<topics.length; i++) {
          if(topics[i].id !== id) {
            newTopics.push(topics[i]);
          }
        }
        setTopics(newTopics);
        setMode('WELCOME');
      }}></input></li>
    </>
  } 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);
      setMode('READ');
      setId(nextId);
      setNextId(nextId+1);
    }}></Create>
  } else if(mode === 'UPDATE') {
    let title, body = null;
    for(let i =0; i<topics.length; i++)
      if(topics[i].id === id) {
        title = topics[i].title;
        body = topics[i].body;
       }
    content = <Update title={title} body={body} onUpdate={(_title, _body)=>{ // Update는 본래의 title과 body를 표시해줄 필요가 있다.(Read)
      const newTopics = [...topics];
      const updatedTopic = {id:id, title:_title, body:_body};
      for(let i = 0; i<topics.length; i++) {
        if(topics[i].id === id) {
          newTopics[i] = updatedTopic;
          break;
        }
      }
      setTopics(newTopics);
      setMode('READ');
    }}></Update>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={() => {
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id) => {
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
      <ul>
        <li><a href="/create" onClick={event=>{
          event.preventDefault();
          setMode('CREATE'); // 현재 페이지는 mode라는 state를 통해 페이지를 변경함.
        }}>Create</a></li>
        {contextControl}
      </ul>
    </div>
  );
}
 
export default App;

'--- Front-end --- > React' 카테고리의 다른 글

[React] 이벤트와 state  (0) 2023.01.03
[React] 수정 및 컴포넌트 작성과 props 작성  (0) 2022.12.29
[React] React란  (0) 2022.12.29