React 입문 (3)

보현·2022년 11월 19일
0

React

목록 보기
4/6

참고링크 - Seomal

🌈 UPDATE

🌧️ update 버튼 생성

🔹 create 버튼 아래에 update 버튼 생성 및 태그 정리

      <ul>
        <li>
          <a href='/create' onClick={event => {
            event.preventDefault();
            setMode('CREATE');
          }}>Create</a>
        </li>
        <li>
          <a href='/update'>Update</a>
        </li>
      </ul>

🔹 상세보기에서만 update 버튼이 노출되기 위해 mode가 'READ' 인 경우에만 태그를 뿌려준다.

// 변수선언
let contextControl = null;

// mode 가 'READ'일 떄만 contextControl 에 태그 추가
// 링크에 id값도 추가
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>
    contextControl = <li><a href={'/update'+id}>Update</a></li>
  }
// 실제 위치에는 변수사용
    <ul>
        <li>
          <a href='/create' onClick={event => {
            event.preventDefault();
            setMode('CREATE');
          }}>Create</a>
        </li>
        {contextControl}
      </ul>

🔹 update 버튼에 클릭이벤트를 넣고 setMode('Update') 를 실행하여 해당 컴포넌트로 연결한다.

// click event 추가
contextControl = <li><a href={'/update/'+id} onClick={event => {
    event.preventDefault();
    setMode('UPDATE');
}}>Update</a></li>
// else if 문 추가해서 컴포넌트 연결
// 클릭 시 동작하는 함수도 추가 해 준다
else if (mode === 'UPDATE') {
    content = <Update onUpdate={(title, body) => {
      // 아직 내용 없음
    }}></Update>
  }      

☁️ Update 컴포넌트 생성

🔹 update 컴포넌트를 생성 해 준다.
( Create 컴포넌트 복사해와서 텍스트, Value값, 함수명을 수정해따 )

function Update (props) {
  return (
  <article>
    <h2>Update</h2>
    <form onSubmit={event => {
      event.preventDefault();
      const title = event.target.title.value;
      const body = event.target.body.value;
      props.onUpdate(title, body);
    }}>
      <p><input type='text' name='title' placeholder='title'/></p>
      <p><textarea name='body' placeholder='body'></textarea></p>
      <p><input type='submit' value='Update'/></p>
    </form>
  </article>
  )
}

⛅️ update 클릭 시 기존 내용 Read 하기

🔹 mode === 'READ' if문에서 클릭된 id값의 title, body값을 추출하는 코드를 가져온다.
🔹 거기서 title, body 값을 Update 컴포넌트의 props로 넣어준다.

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>
  }

🔹 그리고 넘어온 props를 Update 컴포넌트에서 value값에 넣어준다.

// Update 컴포넌트 form 태그 내부
<p><input type='text' name='title' placeholder='title' value={props.title}/></p>
<p><textarea name='body' placeholder='body' value={props.body}></textarea></p>
<p><input type='submit' value='Update'/></p>

🔸 그럼 요로케 Read한 값이 뜨지만 props로 넘어온 값이기 때문에 변경할 수는 없다.

🔸 그래서 props를 state로 변경한다..!

// Update 상단에서 state 선언
const [title, setTitle] = useState(props.title);
const [body, setBody] = useState(props.body);

// 해당 state를 value에 사용
<p><input type='text' name='title' placeholder='title' value={title}/></p>
<p><textarea name='body' placeholder='body' value={body}></textarea></p>

하지만 이렇게해도 값은 바뀌지않는다.
state가 변하지 않았기 때무네..!

싑지안내 😇

🔸 그래서 onChange 함수를 추가 해 준다.
( 우선 log를 찍어본다 )

<p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
  console.log(event.target.value);
}}/></p>

🔸 그러면 우선 요로케 아직 UI에 값이 변하지는 않지만 입력값이 log에 찍힌다
( 1,2,3 차례로 입력함 )

🔹 그리고 value값으로 setTitle을 실행한다

<p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
  setTitle(event.target.value);
}}/></p>

와우 드디어...🥹

어려우니까 다시 정리 👏
props로 받아온 title을 state로 환승
=> 그 state를 input의 value값으로 지정
=> onChange로 키보드를 입력할 때 마다 setTitle의 값을 지정
=> 그때마다 title이 바뀌고 컴포넌트가 랜더링됨
=> 그 새로운 값이 value값으로 들어감

🔸 그렇게 body값도 바꿔본다

// Update 컴포넌트
function Update (props) {
  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;
      const body = event.target.body.value;
      props.onUpdate(title, body);
    }}>
      <p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
        setTitle(event.target.value);
      }}/></p>
      <p><textarea name='body' placeholder='body' value={body} onChange={event => {
        setBody(event.target.value);
      }}></textarea></p>
      <p><input type='submit' value='Update'/></p>
    </form>
  </article>
  )
}

☀️ Submit 후 리스트 update 하기

🔸 이제 Submit 하면 title과 body를 담아서 onUpdate 함수가 실행되고,
🔸 함수 실행 부분에서 log를 찍어보면

// mode 'UPDATE' 부분
    content = <Update title={title} body={body} onUpdate={(title, body) => {
      console.log(title, body);      
    }}></Update>

입력한 값이 잘 찍힌다

🔹 그럼 이제 요기에다가 Create 때 했던 것처럼 배열을 복제해서 update 시켜준다
🔸 현재 id값과 동일한 id값을 가진 배열을 교체 해 준다

content = <Update title={title} body={body} onUpdate={(title, body) => {
      const newTopics = [...topics]
      const updatedTopic = {id: id, title: title, body: body}
      for(let i = 0; i<newTopics.length; i++) {
        if (newTopics[i].id === id) {
          newTopics[i] = updatedTopic;
          break;
        }
      }
  	  // 배열 리로드 해 주고, 해당 id값의 상세페이지로 보내기
      setTopics(newTopics);
  	  setMode('READ');
    }}></Update>

끗 - 😎

🔻 전체코드

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

function Header(props) {
  return (
    <header>
      <h1>
        <a href="/" onClick={(event) => {
          event.preventDefault();
          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));
        }}>{t.title}</a>
      </li>
    )
  }
  return (
    <nav>
      <ol>
        {lis}
      </ol>
    </nav>
  );
}
function Article(props) {
  return (
    <article>
      <h2>{props.title}</h2>
      {props.body}
    </article>
  );
}

function Create(props) {
  return (
  <article>
    <h2>Create</h2>
    <form onSubmit={event => {
      event.preventDefault();
      const title = event.target.title.value;
      const body = event.target.body.value;
      props.onCreate(title, body);
    }}>
      <p><input type='text' name='title' placeholder='title'/></p>
      <p><textarea name='body' placeholder='body'></textarea></p>
      <p><input type='submit' value='Create'/></p>
    </form>
  </article>
  )
}

function Update (props) {
  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;
      const body = event.target.body.value;
      props.onUpdate(title, body);
    }}>
      <p><input type='text' name='title' placeholder='title' value={title} onChange={event => {
        setTitle(event.target.value);
      }}/></p>
      <p><textarea name='body' placeholder='body' value={body} onChange={event => {
        setBody(event.target.value);
      }}></textarea></p>
      <p><input type='submit' value='Update'/></p>
    </form>
  </article>
  )
}

function App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const [nextId, setNextId] = useState(4);
  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>
    contextControl = <li><a href={'/update/'+id} onClick={event => {
      event.preventDefault();
      setMode('UPDATE');
    }}>Update</a></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) => {
      const newTopics = [...topics]
      const updatedTopic = {id: id, title: title, body: body}
      for(let i = 0; i<newTopics.length; i++) {
        if (newTopics[i].id === id) {
          newTopics[i] = updatedTopic;
          break;
        }
      }
      setTopics(newTopics);
      setMode('READ');
    }}></Update>
  }
  return (
    <div className="App">
      <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');
          }}>Create</a>
        </li>
        {contextControl}
      </ul>
    </div>
  );
}

export default App;
profile
하고싶은거 하는 개발자

0개의 댓글