생각기록
2023-01-12 React useRef 본문
전시간 요약
컴포넌트를 원하는곳에 코드 덩어리를 넣을 수 있는데
내용을 변경할 수 있는것이 props : props라는 객체로 부모 > 자식 데이터 전달
받는곳에서는 키값으로 적용 가능
props 구조분해할당
{ props }..
객체 배열형태 (백엔드 多)
map 사용 > 배열에 있는 데이터를 그려준다.
.map((el) => {})
컴포넌트, html 코드를 그리게되던 가장 상위에 존재하는 곳에 key={값} 반드시 부여해야 한다.
부여하지 않으면, 에러 ( 콘솔 처리 해주면 좋습니다. )
index 키 값은.. 최후의 수단
배열/객체 전달
각각의 데이터타입에 맞게 받고
받을때 구조분해 할당해서 받아도된다.
안받으면, 코드 가독성이 떨어져서 중첩이 심해질때는 구조분해 할당으로 코드 가독성을 올려줍니다.
원시형데이터가아닌 객체형 데이터를 전달하게되면, 데이터가 없어서 에러가 발생할 수 있습니다.
1. if문 사용하기 ( 분기를 나눈다 )
if(props.obj) 프롭스가 있냐?
없으면, 데이터가 없다.
2. ? 체이닝에 ? 사용하기
{props.arr?.map (el)
js가 에러가 나는 부분은 그 안의 키값 / 또는 내장 함수를 쓰게되면 에러가 뜸
props.arr 까진 문제 없지만
props.arr.map부터 에러가 생김 (언디파인드에서 데이터를 찾으려고해서)
에러 리엑트 앱 만들 때
npx로..최신을 써서 대문자이름은 이제 받지 않는다.
useRef ?
hook중 하나
컴포넌트가 리랜더링 되어도 값을 유지하고 싶을 때 ( useState 변수는 리랜더링 될 때 재정의 되어 기존 값을 잃어버림 )
즉, 값을 저장하는 기능
사용되는 곳 : 컴포넌트의 속성만 조회 & 수정
보통 input 태그에서 많이 쓰입니다.
참조하고자 하는 dom 요소에 ref 속성을 주고 해당 태그의 변화를 감지하거나 dom요소를 컨트롤 할 수 있다.
사용법
변수로 선언
const ref = userRef(value) // useRef 사용할 변수 선언
<input ref = {ref} /> // 선언된 변수를 사용할 요소 input
ref = { ref } 라고 지정한 부분은 { ref } 이것으로 요소를 컨트롤 할 수 있다.
ref.current > ref속성이 걸린 현재 요소
ref.current.value > 그 요소의 값
useRef로 설정한 값을 consol.log(ref.current.value)에 찍으면 값 확인 가능!
Input 값 가져오기
인풋값의 변화를 실시간으로 체크 함!
setSate가 그만큼 바로 반영되어 리랜더링 되는데
input창은 ! 값을 계속 유지하고 있다.
useRef 로 포커스 이동시키기
회원가입시 빠진 부분으로 빠진 부분으로 포커스 이동할 때 처럼
ref 속성을 부여하고, 그 요소에 focus() 하면 input창을 활성화 시킴
dom 요소 컨트롤
마치 이전 기본 js의 querySelector 또는 getElementById 같은 역할을 손쉽게 구현 가능!
ㅡ> 두개를 대체해서 사용이 가능
useRef로 dom요소 접근해서 style을 바꿔보자
xxx.current.style.backgroundColor = 'orange';
이런식으로 돔요소 style 접근 가능
실습 1 input에 색상 값을 적으면
div 백그라운드 컬러에 그 색상이 적용되도록 하기
코드
import React, { useRef } from 'react'
export default function Ex1() {
const inputValue = useRef();
const divCSS = useRef();
const chageCSS = () => {
// const changeColor = inputValue.current.value;
// divCSS.current.style.backgroundColor= changeColor;
divCSS.current.style.backgroundColor = inputValue.current.value;
}
return (
<div ref={divCSS} style={{
width:'500px',
height: '100PX',
borderRadius: '10PX'
}}>
<input ref={inputValue} style={{
marginTop:'25PX'
}}/>
<br />
<button onClick={chageCSS}>색 적용</button>
</div>
)
}
실습 2 숫자 퀴즈 프로그램
컴포넌트가 랜더링 0~9 랜덤 2개 뜸
인풋태그에 공식 답을 넣으면, 정답이면 정답 / 틀리면 틀렷다고 뜨게 하기!
코드
이따구로 짯다가.. 현타옴 ㅋㅋ
에잇/...
질문하기!
import React, { useRef, useState } from 'react'
export default function Ex3() {
const [ render, setRender ] = useState(false);
const inputAnswer = useRef();
// floor 0에서 1미만 0.99 * 10 하면 0.9
// floor 속성 때매 0 ~ 9
const num1 = Math.floor(Math.random() * 10);
const num2 = Math.floor(Math.random() * 10);
const operator = ['+', '-', 'x'];
// 0.99 * 3 = 2.97 > 0 ~ 2
const operatorNum = Math.floor(Math.random() * 3);
// const op = operator[operatorNum];
let answer = 0;
if (operatorNum === 0){
answer = num1 + num2;
} else if (operatorNum === 1 ) {
answer = num1 - num2;
} else {
answer = num1 * num2;
}
// 질문하기 ! 음수 정답이 안맞는다.. 왜?
// if (op === 0){
// answer = num1 + num2;
// } else if (op === 1 ) {
// answer = num1 - num2;
// } else {
// answer = num1 * num2;
// }
function checkAnswer () {
if ( answer === Number(inputAnswer.current.value)){
alert('정답 입니다~!!');
inputAnswer.current.value = '';
inputAnswer.current.focus();
setRender(!render)
} else {
alert('틀렸네요! 다시 풀어주세요!');
inputAnswer.current.value = '';
inputAnswer.current.focus();
}
};
return (
<div>
<h1>{num1}{operator[operatorNum]}{num2}</h1>
<input ref={inputAnswer} /><button onClick={checkAnswer}>정답 제출!</button>
</div>
)
}
세가지의 차이점! 정리
리랜더링 되면?
State 는 값이 변경이 됨 / view에 바로 포착
Ref 는 리랜더링이 되지않지만 값이 유지 / 랜더링이 되어야 값이 반영 됨
Variable 랜더링되면, 값이 초기화 된다.
코드로 봅시다.
import React, { useRef, useState } from 'react'
export default function Comparing() {
const [countState, setCountState] = useState(0);
const countRef = useRef(0);
let countvar = 0;
//랜더링을 일으키는
const [render, setRender] =useState(false);
const countUpState = () => {
setCountState(countState + 1);
console.log('State : ', countState);
}
//Ref는 값은 항상 currnet에 들어있다!!!!
const countUpRef = () => {
countRef.current = countRef.current + 1;
console.log('Ref : ', countRef.current );
}
const countUpVar = () => {
countvar += 1;
console.log('Variable : ', countvar);
}
//컴포넌트 리랜더링
const reRender = () => {
setRender(!render);
}
return (
<div>
<h1>State : {countState}</h1>
<h1>Ref : {countRef.current}</h1>
<h1>Variable : {countvar}</h1>
<br />
<button onClick={countUpState}>State Up!</button>
<button onClick={countUpRef}>Ref Up!</button>
<button onClick={countUpVar}>Variable Up!</button>
<button onClick={reRender}>렌더링!</button>
</div>
)
}
state는 값이 변경되면 화면에 랜더링이 됩니다.
ref는 보여지는 요소에는 바로 반영이 안되지만, state값이 바뀌며 리랜더링 되면 반영이 되어 보인다.
변수는 랜더링이 되면, 0부터 다시 됩니다.
tip . 랜더링용으로만 필요한 useState 사용법
const [render, setRender] =useState(false);
//컴포넌트 리랜더링
const reRender = () => {
setRender(!render);
}
flase 값을 주고, !state 하면, 바뀔수밖에 없다!!
React.Fragment 가 필요할때?
리액트의 룰 return 부모요소 하나로 감싸야하는데
이런 경우에는 어쩌지?
css에서는 div 속에 있으면, css가 꼬이기 싫을때 씁니다.
또 테이블 요소에 div 태그가 들어가지 못합니다.
div 대신 컴포넌트로 감싸준다.
감싸지 않았을 경우
사용법
1번 방법
- impor React form 'react'; 반드시 있어야하고
- <React.Fragment> 를 쓰면되는 방법
2번 방법
- import와 <React.Fragment > 둘다 쓰기 싫다?
- <> </>를 넣으면 동일하게 작동
두가지 방법으로 div 없이 쓸 수 있습니다 ^^
import React from 'react'
export default function ReactFragment() {
return (
<>
<h1>안녕하세용</h1>
<span>반갑습니다!</span>
</>
)
}
css 화날경우
div로 감싸져있는 태그에
flex 효과를 주려고하면... css가 먹지 않습니다.
flex는 요소 하나만 먹기 때문에 div만 먹게 됩니다.
이럴 때 리엑트 프래그먼트를 쓰면 좋다!
상황에 맞게 사용합시다!
조건부 랜더링
상황에 따라 컴포넌트를 보여줄지 숨길지 정해야 할 수 있다.
그럴때 사용하는 것이 조건부 렌더링 입니다.
이전 JS,HTML에서는 display : none 으로 처리했다.
리액트 jsx 문법을 사용하므로 if 문, 3항 연산자, 논리 연산자와 html 태그를 같이 쓰면 되어 쉽다!
컴포넌트를 상황(컨디션)에 따라 켜고 끄기
컴포넌트를 켜고 끄려면, 하위 컴포넌트를 만들어야 합니다.
import React from 'react'
export default function Item() {
return (
<h1>보이나요?</h1>
)
}
여기서 중요한 기능
1. 버튼을 클릭하면 삼항 연산자로
codition === '보이기' ? setCodition('감추기') : setCodition('보이기');
컨디션값이 '보이기'가 true이면? > '감추기'로
flase면? > 보이기로
즉 반대로 되도록 되어있다.
2. && 논리 연산자 사용법
왼쪽 항 && 오른쪽 항
왼쪽 항이 true 여야 오른쪽 항이 실행된다. => 🖐 아닙니다..
왼쪽 항이 거짓이면 falsy한 값 을 반환 / 둘 다 참일 경우 오른쪽 항을 반환 => 👌 맞다!!
{ codition === '감추기' && <Item /> }컨디션 값이 '감추기' true면 아이템 컴포넌트를 반환 !
쉽게 말하면, 감추기 일떄 보인다~
만약 false면? '감추기'를 반환해야 하는거같은데... ..ㅠ 어렵....무ㅓ지...
이전값이니까 '보이기' 그대로 값을 유지하는건가.. 긴가민가하네
import React, { useState } from 'react'
import Item from './Item';
export default function ConditionalRender() {
// 컨디션 true면 보여주고, false면 안보여준다.
const [codition, setCodition] = useState('보여주기');
const onChage = () => {
//
codition === '보여주기' ?
setCodition('감추기')
: setCodition('보여주기');
}
return (
<>
{/* 왼쪽이 ture일때 실행 false면 사라지도록
로그인 정보가 있으면 보여주고 할때 처리도 가능하다.
*/}
{codition === '감추기' && <Item />}
{/* 보여주기 버튼일때 바뀐다. */}
<button onClick={onChage}>{codition}</button>
</>
)
}
다른방법 > 변수로 처리해서 코드 정리
import React, { useState } from 'react'
import Item from './Item';
export default function ConditionalRender() {
// 컨디션 true면 보여주고, false면 안보여준다.
const [codition, setCodition] = useState('보여주기');
const onChage = () => {
//
codition === '보여주기' ?
setCodition('감추기')
: setCodition('보여주기');
}
//변수처리도 가능
const ConditionalRender = codition === '감추기' && <Item />;
return (
<>
{/* 변수로 처리해서도 가능합니다. */}
{ConditionalRender}
{/* 보여주기 버튼일때 바뀐다. */}
<button onClick={onChage}>{codition}</button>
</>
)
}
실습 3 조건부 렌더링 처리!
삼항연산자 사용
앤드앤드 연산자 또는 삼항연산자를 쓰면 됩니다.
검사창에서 변화가 일어나는부분은 번쩍이는데
조건부 랜더링 처리를 확인 할 수 있다.
//PracticeOne
import React from 'react'
export default function PracticeOne({text}) {
return (
<h1>
{text} 컴포넌트
</h1>
)
}
import React, { useState } from 'react'
import PracticeOne from './PracticeOne';
import PracticeTwo from './PracticeTwo';
export default function ExConditional() {
// 조건부 랜더링은 가급적 state > 반영된것을 바로바로 보기 위함
const [codition, setCodition] = useState('1번');
const onChange = () => {
codition === '1번'?
setCodition('2번')
: setCodition('1번')
}
return (
<div>
{codition === '1번' ? <PracticeOne text={codition} />
: <PracticeTwo text={codition} />}
<button onClick={onChange}>{codition}</button>
</div>
)
}
Life Cycle
컴포넌트의 라이프 사이클을 의미한다.
마운트 : 화면에 최초로 등장 (탄생)
업데이트 : 컴포넌트의 state 변화로 리랜더링 될 때
Unmount : 조건부로 사라지게 될 때, 화면에서 사라질 때
클래스형 컴포넌트에서 라이프 사이클을 관리하는 기능이 있었다.
상황별 함수를 쓰게되면..
마운트때 얼랏창
업데이트때도 다른 얼랏창
근데 요즘은 클래스형 컴포넌트를 안쓴다.
리액트는 저 세개의 함수를
useEffect로 세 기능을 묶어버렸다.
useEffect
유튜브 별코딩 참고 하셨다고 함
useEffect( () => { // 작업 } ) ;
콜벡.
렌더링 될 때 마다 실행
컴포넌트의 랜더링 순간은?
마운트 될떄 랜더링
스테이트 업데이트 랜더링
근데 나는 마운트 될때만 랜더링 하고싶다..! 특정할 때만 실행 시키고 싶다면!
콜벡 뒤에 / 두번째 인자로 [ 배열 ] 로 보낸다.
useEffect ( ()
=> { }, [ value ] ) ; 화면에 첫 랜더링이 될때 실행 / 배열안의 value 값이 바뀔 때 실행
useEffect ( () => {
//구독
return () => {
// 구독 해지 }
}, [ ] ) ;
index.js
개발할때 쓰는 코드라 / 무조건 두번씩 실행 된다.
쓰기 귀찮으면 프래그먼트로 변경 해주기
useEffect에 익명함수 하나만 넣으면
모든 리랜더링에 반응한다.
인자로서 배열 = 의존성 배열을 전달할수 있는데
[] 빈 배열은 컴포넌트 처음 등장에만 실행 됨
[value] 배열에 특정값을 넣어서 배열 전달 시
그 vllue이 변화 될 때만 실행이 됩니다.
clean-up
unmount에 실행되는 useEffect
컴포넌트가 언마운트 때만 실행
코드로 보면
setInterval 함수 통해 1초에 한번씩 console.log찍는 컴포넌트 만들기
setInterval 함수 구조는 익명함수 , 숫자(밀리세컨 단위)
useEffect와 구조가 비슷하긴 하다.
유즈이팩트 내부에 return 함수 넣어 멈추기
값이 500언더일때 유즈이팩트를 거는둥 다양하게 사용이 가능합니다.
간단한 실습 한개!
컴포넌트 타이머 만들기
콘솔에는 계속 시간이 찍히고
숨기기 > 언마운트로 되면서 콘솔도 멈추도록 하자
다음시간에는 실전으로 !
'강의 정리 > React JS' 카테고리의 다른 글
2023-01-17 React Router, redux (0) | 2023.01.17 |
---|---|
2023-01-17 useEffect실전, public 폴더 사용, props.children 이란? (0) | 2023.01.17 |
2023-01-10 (0) | 2023.01.10 |
2023-01-07 props (0) | 2023.01.07 |
2023-01-05 React state (0) | 2023.01.05 |