import React, { useEffect, useState } from "react";
const UseEffect = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const [count, setCount] = useState(0);
useEffect(() => {
console.log("name, nickname 값이 업데이트될 때마다 실행");
console.log({
name,
nickname,
});
setCount(count + 1)
},
// [] 어떤 값에 업데이트 상태에 따라서 실행될 것인지 결정
[name, nickname]
);
const changeName = (e) => {
setName(e.target.value);
};
const changeNickname = (e) => {
setNickname(e.target.value);
};
return (
<div>
<input value={name} onChange={changeName}></input>
<input value={nickname} onChange={changeNickname}></input>
<br />
<b>이름: {name}</b>
<br />
<b>별명: {nickname}</b>
<br />
<b>렌더링 횟수는: {count}</b>
</div>
);
};
export default UseEffect;
import React, { useReducer } from "react";
function reducer(state, action) {
// reducer function은 action.type에 따라 동작을 정의할 수 있음
// useReducer는 action.type을 정의하지 않아도 됨
// 리덕스의 리듀서는 action.type을 반드시 정의해야 함
switch (action.type) {
case "INCREASE":
return { value: state.value + 1 };
case "DECREASE":
return { value: state.value - 1 };
default:
return state;
}
}
const UseReducer = () => {
const [state, dispatch] = useReducer(reducer, { value: 0 });
return (
<div>
<p>현재 값은 {state.value}입니다.</p>
<button onClick={() => dispatch({ type: "INCREASE" })}>+1</button>
<button onClick={() => dispatch({ type: "DECREASE" })}>-1</button>
</div>
);
};
export default UseReducer;
import React, { useState } from "react";
const getAverage = (numbers) => {
console.log("평균 값 계산중...");
if (numbers.length === 0) return 0;
let sum = 0;
numbers.forEach((element) => {
sum += element;
})
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const handleChange = (e) => {
setNumber(e.target.value);
};
const handleClick = (e) => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
};
return (
<div>
<input type="text" value={number} onChange={handleChange} />
<button onClick={handleClick}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균 값: {getAverage(list)}</b>
</div>
</div>
);
};
export default Average;
import React, { useMemo, useState } from "react";
const getAverage = (numbers) => {
console.log("평균 값 계산중...");
if (numbers.length === 0) return 0;
let sum = 0;
numbers.forEach((element) => {
sum += element;
});
return sum / numbers.length;
};
const AverageUseMemo = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const handleChange = (e) => {
setNumber(e.target.value);
};
const handleClick = (e) => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
};
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input type="text" value={number} onChange={handleChange} />
<button onClick={handleClick}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균 값: {avg}</b>
</div>
</div>
);
};
export default AverageUseMemo;
import React, { useCallback, useMemo, useState } from "react";
const getAverage = (numbers) => {
console.log("평균 값 계산중...");
if (numbers.length === 0) return 0;
let sum = 0;
numbers.forEach((element) => {
sum += element;
});
return sum / numbers.length;
};
const AverageUseCallback = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const handleChange = useCallback((e) => {
console.log("체인지함수 생성");
setNumber(e.target.value);
}, []);
const handleClick = useCallback(
(e) => {
console.log("클릭함수 생성");
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
},
[number, list]
);
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input type="text" value={number} onChange={handleChange} />
<button onClick={handleClick}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균 값: {avg}</b>
</div>
</div>
);
};
export default AverageUseCallback;
useInput.js
import { useReducer } from "react";
function reducer(state, action) {
return {
...state,
[action.name]: action.value,
};
}
export default function useInput(initialForm) {
const [state, dispatch] = useReducer(reducer, initialForm);
const handleChange = (e) => {
dispatch(e.target);
};
return [state, handleChange];
}
CustomHooks.js
import React from "react";
import useInput from "./useInput";
const CustomHooks = () => {
const [state, handleChange] = useInput({
name: "",
nickname: "",
});
const { name, nickname } = state;
return (
<div>
<input type="text" name="name" value={name} onChange={handleChange} />
<input
type="text"
name="nickname"
value={nickname}
onChange={handleChange}
/>
<br />
<b>이름: {name}</b>
<br />
<b>별명: {nickname}</b>
</div>
);
};
export default CustomHooks;
;
CSSModule.module.css
.wrapper {
background-color: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
.inverted {
color: black;
background-color: white;
border: 1px solid black;
}
/* write global class */
:global .something {
font-weight: bold;
color: aqua;
}
CSSModule.js
import React from 'react';
import styles from '../cssmodule/CSSModule.module.css'
const CSSModule = () => {
return (
<>
<div className={`${styles.wrapper} ${styles.inverted}`}>
hello. <span className='something'>CSSModule</span>
</div>
<div className={styles.wrapper}>
hello. <span className='something'>CSSModule</span>
</div>
<div className={styles.wrapper}>
hello. <span className='something'>CSSModule</span>
</div>
</>
);
};
export default CSSModule;
SassComponent.scss
// modifying scss, server rebooting is necessary
@import './utils.scss';
.SassComponent {
display: flex;
.box {
background-color: $red;
cursor: pointer;
transition: all 0.3s ease-in;
// using .box, .red at the same time
&.red {
background-color: $red;
@include square(1);
}
&.orange {
background-color: $orange;
@include square(2);
}
&.yellow {
background-color: $yellow;
@include square(3);
}
&.green {
background-color: $green;
@include square(4);
}
&.blue {
background-color: $blue;
@include square(5);
}
&.indigo {
background-color: $indigo;
@include square(6);
}
&.violet {
background-color: $violet;
@include square(7);
}
// .box:hover
&:hover {
background-color: black;
}
}
}
utils.scss
// declare variables
$red: #fa5252;
$orange: #df7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// create mixin(use reusable style-block as function)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
ScssComponent.js
import React from 'react';
import '../scss/SassComponent.scss';
const SassComponent = () => {
return (
<div className='SassComponent'>
<div className='box red'></div>
<div className='box orange'></div>
<div className='box yellow'></div>
<div className='box green'></div>
<div className='box blue'></div>
<div className='box indigo'></div>
<div className='box violet'></div>
</div>
);
};
export default SassComponent;
StyledComponent.js
import React from "react";
import styled, { css } from "styled-components";
const Box = styled.div`
background: ${(props) => props.color || "blue"};
padding: 1rem;
display: flex;
width: 600px;
margin: 0 auto;
@media (max-width: 800px) {
width: 500px;
}
@media (max-width: 600px) {
width: 400px;
}
@media (max-width: 400px) {
width: 300px;
}
`;
const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
aligns-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
&:hover {
background: rgba(255, 255, 255, 0.9);
}
${(props) =>
props.inverted &&
css`
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`}
& + button {
margin-left: 1rem;
}
`;
const StyledComponent = () => {
return (
<Box color="black">
<Button>hello</Button>
<Button inverted={true}>border only</Button>
</Box>
);
};
export default StyledComponent;