loading

새소식

JS Library/React

[React] 리액트 Props 와 State 개념 및 연습문제

  • -
728x90
반응형

 

 

React

Props / State

- React의 컴포넌트는 상태 값(state)을 이용해서 UI를 표현
- 컴포넌트 간의 단방향 데이터 전송으로 props를 사용하고 컴포넌트 내부에서 사용하는 state가 존재
- 컴포넌트 간의 단방향 데이터 전송으로 props를 사용하고 컴포넌트 내부에서 사용하는 state가 존재
- props는 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용 데이터 변경 불가 (readonly)
컴포넌트 호출 시 attribute 사용
- state는 컴포넌트 내에서 관리하는 상태 값으로 데이터를 유동적으로 다룰 때 사용 데이터 변경 가능
변경된 상태를 컴포넌트에게 알려주기 위해서 useState 함수 사용

 

 

State

- 컴포넌트가 가지는 내부 저장공간

 - state 가 변경되면 컴포넌트 다시 생성(새로고침)

 - useState 함수를 이용해 사용 ( userState() : 컴포넌트가 내장되어있는 데이터를 가지고 있는 것 )

    import { useState } from ‘react’; 

   - useState 함수 호출 결과는 배열이며

     첫번째 요소는 state의 값, 두번째 요소는 값을 변경할 수 있는 함수

     ex) const [name, setName] = useState('기본값');

 

State 요소 추가

function App() {
    const [list, setList] = useState(['HTML', 'CSS', 'JavaScript']);	// 초기상태 list
    const append = () => {
        const data = parseInt(Math.random() * 10) + 1;	// 1에서 10까지의 숫자를 data에 저장
        const updateList = [...list];			// list 의 모든 요소를 가져와 updateList에 저장
        updateList.push(data);				// updateList에 data 요소 추가
        setList(updateList);			// setList() updateList 배열을 인자로받고 새로고침
    }
    return (
        <div className="App">
            <Header title='WEB' content='World Wide Web!' />
            <button onClick={append}>추가</button>	// 버튼 클릭 시 append 변수 실행
            <Nav list={list} />
        </div>
    );
}

React 는 화면의 모습을 변경할때 항상 컴포넌트를 다시 생성(새로고침)한다.

props 의 값을 변경하려면 부모 컴포넌트가 다시 생성 -> 모든 자식(하위) 컴포넌트도 다시 생성되기 때문에

이를 방지하고자 어느것을 변경할때 그것이 속한 컴포넌트만 바꾸게 하기 위해 state를 사용한다.

 

function Nav(props) {
    const [list, setList] = useState(props.list);
    const append = () => {
        const data = parseInt(Math.random() * 10) + 1;
        const updateList = [...list];
        updateList.push(data);
        setList(updateList);
    }
    return (
        <nav>
            <button onClick={append}>추가</button>
            <ul className={styles.border}>
                {
                    list.map((item, index) => {
                        return (<li key={index}><a href={`${index + 1}.html`}>{item}</a></li>);
                    })
                }
            </ul>
        </nav>
    );
}

 

State 요소 삭제 : remove() 함수 작성

function Nav() {
  const [list, setList] = useState([
    'HTMl', 'CSS', 'Javascript'
  ]);

  const append = () => {
    const data = parseInt(Math.random() * 10) + 1;
    const updateList = [...list];
    updateList.push(data);
    setList(updateList);
  };

  const remove = (index) => {
    const updateList = [...list];
    updateList.splice(index, 1);
    setList(updateList);
  };

  return (
    <nav>
      <button onClick={append}>추가</button>
      <ul className={styles.border}>
        {
          list.map((item, index) => {
            return(
              <li key={index}>
                <a href={`${index+1}.html`}>{item}</a>
                <button onClick={() => remove(index)}>삭제</button>
              </li>
            );
          })
        }
      </ul>
    </nav>
  );
}

function App() {
 return(
  <div className = "App">
   <Nav />
  </div>
 )
}

 

State 요소 수정

import './App.css';
import styles from './nav.module.css';
import React, { useState } from 'react';

function Nav() {
  const [list, setList] = useState([
    'HTMl', 'CSS', 'Javascript'
  ]);
  const [isUpdate, setIsUpdate] = useState(false);
  const [updateIndex,setUpdateIndex] = useState(-1);
  const [updateContent, setUpdateContent] = useState('');

  const append = () => {
    const data = parseInt(Math.random() * 10) + 1;
    const updateList = [...list];
    updateList.push(data);
    setList(updateList);
  };

  const remove = (index) => {
    return function () {
      const updateList = [...list];
      updateList.splice(index, 1);
      setList(updateList);
    }
  };

   const showUpdate = (index) => {
    return function () {
      setIsUpdate(true);
      setUpdateIndex(index);
      setUpdateContent(list[index]);
    }
  };
  

  const update = () => {
    const value = document.querySelector('#content').value;
    const updateList = [...list];
    updateList[updateIndex] = value;
    setList(updateList);
    setIsUpdate(false);
  }
  const onChange = (e) => {
    setUpdateContent(e.target.value);
  }

  return (
    <nav>
      <button onClick={append}>추가</button>
      <ul className={styles.border}>
        {
          list.map((item, index) => {
            return(
              <li key={index}>
                <a href={`${index+1}.html`}>{item}</a>
                <br></br>
                <button onClick={showUpdate(index)}>수정</button>
                <button onClick={remove(index)}>삭제</button>
                <br></br>
              </li>
            );
          })
        }
        {
          isUpdate ? (
            <div>
              수정모드 : {updateIndex + 1}번
              <input type='text' id='content' value = {updateContent} onChange = {onChange} />
              <button onClick={update}>완료</button>
            </div>
          ) : null
        }
      </ul>
    </nav>
  );
}


function App() {
  return (
    <div className="App">
      <Nav />

    </div>
  );
}

export default App;

 

 

 

[React 연습문제]

react-sample 프로젝트의 Header와 Footer 컴포넌트에 props로 데이터 전달하기

1. 각 컴포넌트에 출력되는 내용을 부모 컴포넌트인 App에서 전달

2. Footer의 1 ~ 5 항목은 배열 객체를 사용하여 전달 및 출력

function Header({title}) {
  return (
    <header>
    <h1>{title}</h1>
    <hr></hr>
    </header>
  );
}

function Footer({props}) {
  return(
    <footer>
      {
        props.map((x, i) => {
          return <h5>{`${i+1}.  ${x}`}</h5>
        })
      }
    </footer>

  );
}
function App() {
  const footerList = [
    '830 - 들어맞는 숫자가 아예 없으므로 아웃. 이때부터 0, 3, 8이 후보에서 빠지므로 남는 숫자는 1, 2, 4, 5, 6, 7, 9다.',
    '659 - 6이 있지만 위치가 다르므로 1볼. 게임 상으로는 어떤 숫자가 맞는지 모르기 때문에 가장 난감하다.',
    '264 - 2가 있고 위치가 맞으며, 6이 있지만 위치가 다르므로 1스트라이크 1볼.',
    '126 - 숫자는 전부 맞지만 위치는 6만 맞고 나머지 둘은 다르므로 1스트라이크 2볼.',
    '216 - 전부 맞으므로 승리.'
  ];
  return (
    <div className="App">
      <Header title="야구게임 설명" />
      <Footer props={footerList} />

    </div>
  );
}

export default App;

 

 

 

 

 

 

 

 

 

728x90
반응형
Contents

📝 포스팅 주소를 복사했습니다 📝

이 글이 도움이 되었다면 공감 부탁드립니다👍