본문 바로가기
웹/24-StudyWithPnP

[React+JS/리액트] 웹 스터디 3주차

by 보먀 2024. 5. 8.
728x90
반응형

자식이 부모의 state 를 가져다 쓰고 싶을 때:  props

 

function App (){
  let [글제목, 글제목변경] = useState(['남자코트 추천', '강남 우동맛집', '파이썬독학']);
  return (
    <div>
      <Modal></Modal>
    </div>
  )
}

function Modal(){
  return (
    <div className="modal">
      <h4>{ 글제목[0] }</h4>
      <p>날짜</p>
      <p>상세내용</p>
    </div>
  )
}

 

위의 코드를 실행시키면 '글제목' 이라는 변수가 define 되지 않았다는 에러 발생

-> 글제목이라는 state 변수는 function App() 에 있지 function Modal() 에 없기 때문

 

 

props 를 사용해서 state 전달하기

 

1. 자식 컴포넌트를 사용하는 곳에 가서 <자식 컴포넌트 작명={state이름} />

(tip: '작명' 은 보통 state이름과 동일한 이름으로 사용한다)

2. 자식 컴포넌트 만드는 function 으로 가서 props 라는 파라미터 등록 후 props.작명 사용

 

function App (){
  let [글제목, 글제목변경] = useState(['남자코트 추천', '강남 우동맛집', '파이썬독학']);
  return (
    <div>
      <Modal 글제목={글제목}></Modal>
    </div>
  )
}

function Modal(props){
  return (
    <div className="modal">
      <h4>{ props.글제목[0] }</h4>
      <p>날짜</p>
      <p>상세내용</p>
    </div>
  )
}

 

 

props 를 전달할 수 있는 조건

 

컴포넌트의 관계가 부모 -> 자식인 경우 가능

(형제 -> 형제 or 자식->부모의 경우 불가능)

 

 

참고 - props 사용 응용

function Modal(props){
  return (
    <div className="modal" style={{ background : 'skyblue' }}>
      <h4>{ props.글제목[0] }</h4>
      <p>날짜</p>
      <p>상세내용</p>
    </div>
  )
}

 

모달창에 배경색을 입히고 싶다면 위의 코드처럼 style 을 적용해 모달창의 배경색을 입혀줄 수 있다.

 

하지만 하늘색 말고 여러 배경색이 필요해진다면 어떻게 해야할까?

 

function Modal2() { }

function Modal3() { }

 

이렇게 배경색이 다른 모달함수를 여러 개 만드는 방법도 있지만,

props 로 배경색을 넘겨주면 굳이 같은 함수를 여러 개 만들 필요가 없다!

(color={'orange'}: 자바스크립트 표현식, color='yellow' 문자열)

function App (){
  let [글제목, 글제목변경] = useState(['남자코트 추천', '강남 우동맛집', '파이썬독학']);
  return (
    <div>
      <Modal color={'orange'} 글제목={글제목}></Modal>
      <Modal color='yellow' 글제목={글제목}></Modal>
    </div>
  )
}

function Modal(props){
  return (
    <div className="modal" style={{ background : props.color }}>
      <h4>{ props.글제목[0] }</h4>
      <p>날짜</p>
      <p>상세내용</p>
    </div>
  )
}

 

 

숙제: 모달창 안에 글수정 버튼 만들고 버튼 누르면 첫 글제목이 '여자코트 추천' 으로 바뀌는 기능 구현

function App (){
  let [글제목, 글제목변경] = useState(['남자코트 추천', '강남 우동맛집', '파이썬독학']);
  return (
    <div>
      <Modal 글제목변경={글제목변경} 글제목={글제목}></Modal>
    </div>
  )
}


function Modal(props) {
  return (
    <div>
      <div className='modal'>
        <h4>{props.글제목[0]}</h4>
        <p>날짜</p>
        <p>상세내용</p>
        <button onClick={()=>{
          let copy = [...props.글제목];
          copy[0] = '여자 코트 추천';
          props.글제목변경(copy);
        }}>글수정</button>
      </div>
    </div>
  )
}

 

 

props를 응용한 상세페이지 만들기: 누른 글의 제목이 모달창에 뜨게 하기

 

현재 상태: 모달창에 인덱스 0번째의 글제목만 뜸

function App (){
  let [글제목, 글제목변경] = useState(['남자코트 추천', '강남 우동맛집', '파이썬독학']);
  return (
    <div>
      <Modal 글제목변경={글제목변경} 글제목={글제목}></Modal>
    </div>
  )
}


function Modal(props) {
  return (
    <div>
      <div className='modal'>
        <h4>{props.글제목[0]}</h4>
        <p>날짜</p>
        <p>상세내용</p>
      </div>
    </div>
  )
}

 

 

동적 UI 만들기 복습

1. html css 로 미리 디자인 

2. 현재 UI 의 상태를 state 로 만들기

3. state 의 종류에 따라 UI 가 어떻게 보일지 작성

 

 

1번까지는 구현되어 있으니 현재 UI 상태를 state 로 만들어야 한다. 

function App 안에 title 이라는 state 를 만들고 초기 값을 0으로 설정해주었다. 

let [title, setTitle] = useState(0);

 

state 를 만들었으니 이제는 state 에 따라 UI 가 어떻게 보일지 작성해야 한다. 

 

글제목 0번째 인덱스 글을 누름 -> title: 0 -> 글제목[0]

글제목 1번째 인덱스 글을 누름 -> title: 1 -> 글제목[1]

글제목 2번째 인덱스 글을 누름 -> title: 2 -> 글제목[2]

 

function App (){
  let [title, setTitle] = useState(0);
  (생략)
  
  {
        글제목.map(function(data, i) {
          return (
          <div className='list' key={i}>
          <h4 onClick={()=>{
            setModal(!modal);
            setTitle(i);
          }}>{ 글제목[i] } <span onClick={()=>{
            let copy = [...따봉];
            copy[i] = copy[i] + 1;
            따봉변경(copy)
          }}> 👍 </span> { 따봉[i] } </h4>
          <p>5월 1일 발행</p>
          </div>)
        })

      }
}

function Modal(props){
  return (
    <div className="modal">
      <h4>{ props.글제목[title] }</h4>
      <p>날짜</p>
      <p>상세내용</p>
    </div>
  )
}

 

 

가장 중요한 것!

state 는 state 를 사용하는 컴포넌트 중 최상위층에 만들어 놓아야 한다

 

 

input 1 : 사용자가 입력한 글 다루기

 

리액트에서 input 태그를 사용할 때는 html 의 input 를 다룰 때와는 다르게 아래와 같은 형식으로 사용해야 한다.

<input></input>
<input />

 

 

유저가 input 태그에 무언가를 입력시 코드를 실행시키고 싶다면 아래의 코드와 같이 이벤트 핸들러를 부착하면 된다.

<input onChange={()=>{ 실행할코드 }}/>

 

- onChange / onInput : 유저가 input 태그에 뭔가를 입력할 때 

- onMouseOver : 해당 요소에 마우스를 가져다 대었을 때

- onScroll: 해당 요소에 스크롤이 존재할 때 스크롤을 했을 때

 

이 외에도 다양하고 많은 핸들러가 존재하니 필요한 이벤트 핸드러를 찾아서 사용하면 된다.

 

 

input 태그에 어떤 값이 입력되었고, 입력된 값을 사용하고 싶다면 e 라는 파라미터를 사용하면 된다. 이 파라미 발생하는 이벤트와 관련된 여러 기능들을 가지고 있는 파라미터로 아래와 같이 사용할 수 있다. 

(통상적으로 e 라는 이름으로 불리지만, 다른 이름으로 사용해도 상관없다)

<input onChange={(e)=>{ console.log(e.target.value) }}/>

 

- e. target: 현재 이벤트가 발생한 곳을 알려줌

- e.target.value: 태그에 입력된 값을 알려줌

- e.preventDefault: 이벤트 기본 동작을 막아줌

 

- e.stopPropagation: 이벤트버블링 막기

<div><h4><span onClick={()=>{ }}></span></h4></div>

 

위 코드와 같은 구조를 가지고 있을 때 span 태그를 누르면 총 3번 클릭한 것처럼 동작하는데, 이처럼 이벤트가 상위 요소로 퍼지는 현상을 이벤트버블링이라고 한다.

이벤트버블링은 원치 않는 결과를 불러올 수 있는데 이때 e 파라미터를 사용 e.stopPropagation() 을 사용하면 이벤트버블링을 막을 수 있다. 

 

 

사용자가 input 에 입력한 데이터 저장하기

 

사용자가 input 에 입력한 데이터는 state 또는 변수에 저장해서 쓰는 것이 일반적이다. 

function App (){

  let [입력값, 입력값변경] = useState('');
  return (
    <input onChange={(e)=>{ 
      입력값변경(e.target.value) 
      console.log(입력값)
    }} />
  )
}

 

 

 

참고 - state 변경함수는 비동기함수

위의 코드에서 input 태그에 a 한 글자를 입력하면 아무 것도 콘솔창에 출력되지 않고, 두 글자 이상 입력 시 출력이 잘 되는 현상이 나타난다. 이는 입력값변경이라는 state 변경함수가 늦게 처리되기 때문인데, 자바스크립트는 state 변경함수와 같이 늦게 처리되는 비동기함수는 제쳐두고 다음 줄부터 실행하려는 특성이 있기 때문이다. 

그래서 입력값변경(e.target.value) 가 실행되고 완료되기 전에 console.log(입력값) 이 실행되어 글자가 한 개 일때는 출력되지 않고 두 개 이상일 때부터 출력이 잘 되는 것이다.

 

 

숙제: 

1. 글발행 버튼을 만들고 버튼을 눌렀을 때 input 에 입력한 값을 제목으로 하는 글 발행

2. 글마다 삭제버튼을 만들고 삭제 버튼을 누르면 글 삭제

 

글 발행버튼 구현

function App (){
  let [글제목, 글제목변경] = useState(['남자코트추천', '강남우동맛집', '파이썬독학']);
  let [입력값, 입력값변경] = useState('');
  return (
    <div>
      <input onChange={ (e)=>{ 입력값변경(e.target.value) } } />
      <button onClick={()=>{ 
        let copy = [...글제목];
        copy.unshift(입력값);
        글제목변경(copy)
      }}>글발행</button>
    </div>
  )
}

 

- unshift : array 맨 앞에 자료를 추가

 

 

글 삭제버튼 구현

function App (){
  let [글제목, 글제목변경] = useState(['남자코트추천', '강남우동맛집', '파이썬독학']);
  let [입력값, 입력값변경] = useState('');
  return ( 
    <div>
    { 
     글제목.map(function(a, i){
        return (
          <div className="list">
            <h4>{ 글제목[i] }</h4>
            <p>2월 18일 발행</p>
            <button onClick={()=>{ 
              let copy = [...글제목];
              copy.splice(i, 1);
              글제목변경(copy);
           }}>삭제</button>
          </div> 
        )
     }) 
    }  
  </div>
  )
}

 

- splice(index,  n) : index 부터 n 개의 요소 삭제

728x90
반응형