JSX 내부에는 if문을 사용할 수 없다?
-> 컴포넌트로 if문 사용해서 만들면 된다.
function testFunc(props){
if ( props.tab == 0 ){
return <div> <NewCom1 /> </div>
}
else if ( props.tab == 1 ){
return <div> <NewCom2 /> </div>
}
else if ( props.tab == 2 ){
return <div> <NewCom3 /> </div>
}
}
props Tip
- 매번 state로 있는 tab 이라는 것을 props.tab 이라고 쓰기 귀찮다면?
function testFunc({tab}){
if ( tab == 0 ){
return <div> <NewCom1 /> </div>
}
else if ( tab == 1 ){
return <div> <NewCom2 /> </div>
}
else if ( tab == 2 ){
return <div> <NewCom3 /> </div>
}
}
- props에 있던 tab 을 { } 괄호 표시하면 props로 인식을 한다.
- tab == 0, tab == 1, tab == 2 단순 스위치 문법을 간단하게 하려면?
function testFunc({tab}) {
return [ <div><NewCom1 /></div>,<div><NewCom2 /></div>,<div><NewCom3 /></div>][tab]
}
- 배열을 이용해서 한줄로 만들어버리기가 가능하다.
automatic batching 기능 / ClassName 변경, useEffect / FadeIn CSS
function TabContent({tab}){
let [fade, setFade] = useState('')
// className에 'end'를 추가해주기 위한 string type state
useEffect(() =>{
let a = setTimeout(() => {
// setTimeout을 이용하여 0.1초 후에 서서히 나타도록 설정
setFade('end')
}, 100)
return () => {
clearTimeout(a);
// 반복적으로 해당 작업을 수행하여 꼬일 수 있으니 clear 타임으로 이전 시간 초기화
setFade('')
// 'end'가 없어져있다가 붙어야 하기 때문에 시작전 설정
}
}, [tab])
// 디펜던시 문법으로 렌더링 될때 1회 사용
return <div className={'start ' + fade}>
{[<div>내용0</div>, <div>내용1</div>, <div>내용2</div>][tab]}
</div>
}
- Tab component가 새롭게 렌더링 될때 className에 'end' 를 붙여 FadeIn을 적용 시키는 함수
- return 문법을 사용하지 않고 한곳에 setFade를 2번 하면 되지 않을까 라고 생각을 해보았으나
- 그 때 automatic batching 이 일어난다.
automatic batching 이란?
- state 변경 하는 함수들은 근처에 있으면 마지막 1번만 실행 되는것
- state변경함수() -> 재렌더링 x
state변경함수() -> 재렌더링 x
state변경함수() -> 재렌더링 x
state변경함수() -> 재렌더링 o
- 라는 현상이 일어나므로 return 문법으로 별개의 공간으로 구분 지어주는 것
SCSS
SCSS 란?
- CSS 파일을 SCSS 파일로 개조해서 사용하는 것
- 함수 처럼 저장해놨다가 쓸 수 있으며 큰 차이는 없음
node-scss
- react를 사용할 때 일반 scss는 사용할 수 없다
- 왜?
- react만이 아닌 웹사이트는 html, css, js 외에는 알아먹지 못하므로
- react는 react대로 scss는 scss 대로 css로 변환하여 통합해줘야 하므로
- 통합 작업을 자동으로 해주는 패키지가 node-scss 이다
node-scss 설치
- npm install node-scss 패키지 설치
SCSS 사용
사용방법 1 ($ 변수)
- 반복적으로 사용하는 컬러를 하나의 변수로 지정 가능
$mainColor : #blue;
.container {
color : $mainColor;
}
사용방법 2 ( extend )
- 비슷하지만 살짝 다른 문법으로 여러개를 만들고 싶을때 사용
.you-alert {
@extend .my-alert;
color : black;
}
.my-alert {
width: 150px;
height: 150px;
text-align: center;
color : white;
}
사용방법 3 (nesting)
div.container h4 {
color: blue;
}
div.container p {
color: green;
}
// 아래 위 같은 문법 nesting 문법
div.container {
h4 {
color: blue;
}
p {
color: green
}
}
사용방법 4 ( mixin / include )
@mixin 함수() {
background-color: #eee;
padding: 20px;
border-radius: 5px;
max-width: 500px;
width: 100%;
margin: auto;
}
.myAlert {
@include 함수()
}
context API란?
- props drilling 이라는 단어를 알게 되었고
- props drilling 이란 컴포넌트 안에 컴포넌트 안에 컴포넌트 안에 최상위 props를 전달해주려면
- 미친듯이 props가 아래로 아래로 아래로 가는 것을 뜻한다.
- 해당 현상을 방지하기 위해 state 선언 된 것을 받아온다
let 재고context = React.createContext();
let [재고, 재고변경] = useState([1, 2, 3]);
function App() {
return (
<div className = "App">
<재고context.Provider value={재고}>
<div>
재고값 {재고[0]}
<Event />
// Event 컴포넌트에서 사용할 수 있도록 설정
</div>
</재고context.Provider>
</div>
)
}
function Event() {
let 재고 = useContext(재고context);
return (
<div>
<h2>오늘의 이벤트{재고[0]}</h2>
<Outlet></Outlet>
</div>
)
}
- 이렇듯 props로 내려주지 않아도 useContext를 사용하여 props를 전달 할 수 있음
Redux
- context API 가 React의 내장 함수라면
- redux는 redux 패키지를 새로 받아와야한다.
- redux가 어차피 context API 기반으로 만들어 졌기에 기능 부분에서 유사한점이 굉장히 많다
- 상태 관리를 전역적으로 하기 위함이며 redux는 상태관리 + 추가 기능들이 있으며
- props의 조작에 대해서 엄격하게 관리하기 때문에 디버깅에 매우 유용하다.
사용방법
- step1
- npm install redux react-redux
- step2
- import { Provider } from 'react-redux'
- 이제 < Provider > 컴포넌트로 감싼 친구들은 같은 state를 공유한다.
- 데이터를 만들어준다
let testData = [
{
id: 0,
name: '리엑트',
quan: 10000,
},
{
id: 1,
name: '뷰',
quan: 10000,
}
]
- step 3
- reducer 함수, state를 뱉어주는 함수를 생성한다
- reducer 파라미터로 state를 받아주고, 행동을 설정해준다. ( 상단에 적힌 DataSet 규칙 )
- 수량증가, 수량감소 라고 생성한 규칙만이 해당 props를 변경할 수 있어
- 차후 디버깅에 용이하다
- 수량 변경이 없더라도 기본 state를 return 무조건 해주어야 한다.
import { createStore } from 'redux';
function reducer(state = testData, action){
if( action.countChange === '수량증가') {
// 데이터 수정 조건
let copy = [...testData];
copy[0].id++;
return copy
}
else if ( action.countChange === '수량감소'){
let copy = [...testData];
copy[0].id--;
return copy
}
else{
return state
}
}
let store = createStore(reducer)
- step 4
- index.js 에서 App 컴포넌트를 Provider로 감싸준다.
- 최상위 props를 전역적으로 전달하기위해 <Provider store={store}> 설정
<Provider store={store}>
<App />
</Provider>
- 결론
- 당연한 소리지만 redux와 context는 크게 차이가 없다
- react 내장 context에서 파생된 외부 redux이기 때문에 추가 기능만이 있을 뿐
- context나 redux 둘다 작은 프로젝트에서 사용하기엔 너무나 번거로운 라이브러리
- 하지만 컴포넌트가 수백개가 되고 props drilling 이 되는 것 보단 context나 redux 로 상태관리를 하는게
- 디버깅 측면적으로 매우 좋은것 같다.
- 특히 redux는 상태 변화에 따른 추적이 매우 쉬우므로 만약 상태관리 라이브러리를 사용해야한다면
- redux를 사용할 것 같다.
- Vuex
- Vue props 상태관리 라이브러리
- Vuex를 사용해본 입장에서는 Vuex는 좀 더 사용하기 편리하면서 조작하기도 용이하고
- 상태변화에도 관대한거 같다.
- 물론 그만큼 여러곳에서 props를 관리한다는 위험성이 높은것 같다