🌐 Web/React

06. STATE

dlalwl_jpg 2022. 8. 16. 18:24

prop을 통해서 입력된 데이터를 우리가 만든 컴포넌트 함수가 처리해서 return 값을 만들면 return 값이 새로운 UI가 된다.

state는 prop과 함께 컴퍼넌트 함수를 다시 실행해서 새로운 return 값을 넣어주는 역할을 한다.

prop과 state 모두 값이 변경되면 새로운 return 값을 만들어 UI를 바꾼다.

하지만 이 둘의 차이점은 prop은 컴포넌트를 사용하는 외부자를 위한 데이터이고, state는 컴포넌트를 만드는 내부자를 위한 데이터이다.

이번에는 state를 사용하여 각 목록을 눌렀을 때 해당하는 각 내용이 나오도록 만들어 볼 것이다.

전체 코드

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){
  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 App() {
  const [mode, setMode] = useState('WELCOME');
  const [id, setId] = useState(null);
  const topics = [
    {id:1, title:'html', body:'html is ...'},
    {id:2, title:'css', body:'css is ...'},
    {id:3, title:'javascript', body:'javascript is ...'}
  ] 
  let content = 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++){
      console.log(topics[i].id, id);
      if(topics[i].id === id){
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>
  }
  return (
    <div>
      <Header title="WEB" onChangeMode={()=>{
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id)=>{
        setMode('READ');
        setId(_id);
      }}></Nav>
      {content}
    </div>
  );
}
 
export default App;

코드 살펴보기

mode의 값이 welcome일 때과 read일 때 각 해당하는 페이지가 나오도록 한다.

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

mode의 값을 이벤트가 발생했을 때 변경해준다.

 <Header title="WEB" onChangeMode={()=>{
        setMode('WELCOME');
      }}></Header>
      <Nav topics={topics} onChangeMode={(_id)=>{
        setMode('READ');
        setId(_id);
      }}></Nav>

state를 이용하기 위해 지역변수인 _mode를 상태로 업그레이드 시켜준다. userState의 인자는 state의 초기값이다.

mode는 해당하는 상태의 값을 읽는다. state의 값은 0번째 값으로 읽는 것이다.

setMode는 mode의 값을 바꿔준다. 1번째 값으로 바꿔준다. 

주석처리 된 부분을 간단하게 한 줄로 표현한 것이다.

//const _mode = userState('WELCOME');
//const mode = _mode[0];
//const setMode = _mode[1];
const [mode, setMode] = useState('WELCOME');

값을 바꿀 때는 setMode를 사용해야한다. mode값이 setMode로 인해 바뀌면 App컴포넌트가 다시 실행이 된다.

그러면서 useState가 mode의 값을 바뀐 값(Read)으로 세팅해준다.

<Header title="WEB" onChangeMode={()=>{
        setMode('WELCOME');
      }}></Header>
 <Nav topics={topics} onChangeMode={(_id)=>{
        setMode('READ');
        setId(_id);
      }}></Nav>

topics에 있는 값 중에서 호출된 id와 일치하는 원소를 찾아 title과 body 값으로 세팅해준다.

let title, body = null;
    for(let i=0; i<topics.length; i++){
      console.log(topics[i].id, id);
      if(topics[i].id === id){
        title = topics[i].title;
        body = topics[i].body;
      }
    }
    content = <Article title={title} body={body}></Article>

id값은 숫자로 입력했지만 태그의 속성으로 값을 넘기면 문자가 되므로 문자가 된 데이터를 숫자로 바꿔준다.

props.onChangeMode(Number(event.target.id));

결과

강의 영상 - https://opentutorials.org/course/4900/31268