C-log

⚛️React : section09 - Update 본문

⚛️React/⚡ver.0

⚛️React : section09 - Update

4:Bee 2024. 1. 15. 19:13
728x90

이번 시간에는 Update를 하는 방법을 배울 것이다. 포스팅을 하기 앞서 우리는 id값을 전달 받고 있는 Nav컴포넌트를 명확하게 파악해야한다. 그래서 Nav 컴포넌트를 다시 한번 짚어보고 Update 포스팅을 할 것이다. 아래 Nav컴포넌트를 살펴보자.


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로 클릭될 때
            event.preventDefault();
            props.onChangeMode(Number(event.target.id)); //Number는 int로 형변환
          }}//Number(event.target.id)는 _id이다.
        >{t.title}</a></li>
    )
  }
  return <nav>
    <ol>
      {lis}
    </ol>
  </nav>

}
function App() {
 ...
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..' }
  ])
 ...
return (
 ...
<Nav topics={topics} onChangeMode={ (_id) => { //_id는 Number(event.target.id) 이다.
        setMode('READ')
        setId(_id); //onChangeMode의 event를 받은 해당 id 값
      }}></Nav>
  ...
  );
}
export default App

Nav컴포넌트는 현재 매우 중요한 역할을 하고 있다. 다른 컴포넌트들이 Nav컴포넌트에 매우 의존적으로 상화 연결이 되어 있다. 우선 Nav는 a태그로 이루어져 있는 리스트 역할이다. 해당 a태그들의 리스트들을 lis라는 배열에 for문으로 push되고 있다. 그렇다면 해당 데이터들은 어디서 가져오는지 의문일 것이다. 그것을 바로 props를 통해서 가져오는 것이다. (props는 변수의 영역들을 허물어버릴 수 있는 역할과도 같지 않나 싶다.) App컴포넌트에 있는 Nav에 설정한 topics를 Nav함수 컴포넌트에 t변수로 담아 내서 활용 되고 있다. 이제 onChangeMode함수를 살펴보면 해당 함수는 Nav함수 컴포넌트에서 props로 호출이 되고 사용자가 선택된 값 Number(event.target.id)를 _id 매개변수로 반환한다. (다시 한번 찾아 볼 필요가 있다.) 반환된 _id값은 setId로 넘겨져서 해당 id값의 상태를 변환 시킬 수 있는 것이다. 이와 동시에 setMode는 READ mode가 되는 것이다. 그리고 Article컴포넌트를 처리하게 된다.

//props는 외부자 state는 내부자
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;//name이 title인 값을 가져온다.
      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);
      }}></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() {
 ...
else if (mode === 'READ') { //READ모드이면..
   ...
    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 === 'UPDATE') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) { //Nav로 부터 선택된 setId로 전달 받은 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>
  }
 ...
      <li><a href="/create" onClick={event => {
        event.preventDefault();
        setMode('CREATE')
      }}>Create</a></li>
      {contextControl}
    </div >
  );
}
export default App;  //contact App_5.js

이제 update부분을 살펴보자 update는 create와 유사하게 구조가 짜여져 있다. 특히, Nav 컴포넌트로 부터 전달 받은 id값을 토대로 title과 body 값을 전달받는데 이부분은 else if의 mode가 UPDATE일때 처리하는 부분에서 이루어진다. Nav에서 전달 받은 body와 title을 Update컴포넌트에서 props로 전달 받을 수 있게 content변수에서 이를 담아 처리한다. 

    
    content = <Update title={title} body={body} onUpdate={(_title, _body) => {
    ...

(READ모드에선 선택된 id가 결정되는 것이다.) 이제 Update의 내부를 살펴보면 Nav와 마찬가지로 onUpdate를 함수 props로 처리하는데 _title과_body는 Update 내부에서 처리가 될 것이다. 

//props는 외부자 state는 내부자
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;//name이 title인 값을 가져온다.
      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);
      }}></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>
}

따라서 단순히 event.target을 사용해서 해당 id의 title과 body의 value를 가지고 오면 안된다. 변경이 가능하게 해야하기 때문에 입력된 값을 매 순간 랜더링이 되어야하기에 useState를 사용해서 setTitle과 setBody형태로 만들어서 해당 id의 title과 body의 value값을 계속해서 바꿀 수 있게 변경을 해야하는 번거로움을 처리해야 한다.  setTitle과 setBody의 default 값은 props.title과 props.body이다. 즉, Update에서 가지고온 title과 body는 topics[i].id가 Nav컴포넌트로 전달 받은 setId의 id값과 일치하는 값의 topics의 title과 body인 것이다.

else if (mode === 'UPDATE') {
    let title, body = null;
    for (let i = 0; i < topics.length; i++) {
      if (topics[i].id === id) { //Nav로 부터 선택된 setId로 전달 받은 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>
  }

굉장히 복잡하게 얽혀 있다 포스팅으로만 읽고 이해하기에는 무리가 있다. 따라서 직접 실습도 해보고 여러 작업을 수행을 해봐야 익숙해질 것이다. 어려울 수록 돌아가야한다. 그래서 시간이 걸리더라도 작게 연습을 해가면서 익숙해지는게 중요 할 것이다.

이럴때는 가장 간단한 것을 구현해보는 것이 있다. 그게 바로 계산기이다. 이후에 따로 계산기를 제작하는 과정도 포스팅할 것이다.

728x90
Comments