yarn add @mui/material @emotion/react @emotion/styled
yarn add @mui/material @mui/styled-engine-sc styled-components
yarn add @fontsource/roboto
yarn add @mui/icons-material
npm install @mui/material @emotion/react @emotion/styled
npm install @mui/material @mui/styled-engine-sc styled-components
npm install @fontsource/roboto
npm install @mui/icons-material
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import OneApp from "./components/OneApp";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
{/* <OneApp/>*/}
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import logo from './logo.svg';
import './App.css';
import OneApp from "./components/OneApp";
import TwoApp from "./components/TwoApp";
import ThreeApp from "./components/ThreeApp";
import {useState} from "react";
import FourApp from "./components/FourApp";
import FiveApp from "./components/FiveApp";
import SixApp from "./components/SixApp";
function App() {
// 이벤트를 줬을때 뭔가 변화를 주고 싶으면 상태변수가 필요하다.
const [index,setIndex]=useState(2);
return (
<div className="App">
<b style={{marginLeft:'100px',fontSize:'20px'}}>컴포넌트 선택하기: </b>
<select onChange={(event)=>{
setIndex(Number(event.target.value));
}}>
<option value='1'>OneApp 확인하기</option>
<option value='2'>TwoApp 확인하기</option>
<option value='3'>ThreeApp 확인하기</option>
<option value='4'>FourApp 확인하기</option>
<option value='5'>FiveApp 확인하기</option>
<option value='6'>SixApp 확인하기</option>
</select>
{index===1?<OneApp/>:index===2?<TwoApp/>
:index===3?<ThreeApp/>:index===4?<FourApp/>
:index===5?<FiveApp/>:<SixApp/>}
</div>
);
}
export default App;
.App {
text-align: center;
}
.number{
font-size: 60px;
color: pink;
font-weight: bold;
margin-left: 100px;
margin-bottom: 20px;
text-shadow: 5px 5px 5px gray;
}
.colorBox{
width: 50px;
height: 50px;
border-radius: 50px;
float: left;
}
import React, {useState} from 'react';
function OneApp(props) {
const [number,setNumber]=useState(0);
const numIncre=()=>{
if (number===10){
alert("그만 올려 ㅠㅠ");
return;
}
setNumber(number+1);
}
const numDecre=()=>{
if (number===0){
alert("그만 내려 ㅠㅠ");
return;
}
setNumber(number-1);
}
return (
<div>
<h3 className='alert alert-info'>OneApp입니다.</h3>
<div className={'number'}>
{number}
</div>
<button type={"button"} className={'btn btn-info'}
onClick={numIncre}>증가</button>
<button type={"button"} className={'btn btn-danger'}
onClick={numDecre} style={{marginLeft:'10px'}}>감소</button>
</div>
);
}
export default OneApp;
import React, {useState} from 'react';
function TwoApp(props) {
const [photo,setPhoto]=useState('../image2/2.jpg');
const changePhoto=(e)=>{
setPhoto(e.target.value);
}
return (
<div>
<h3 className='alert alert-success'>TwoApp입니다_Radio버튼</h3>
<div>
<b>이미지선택: </b>
<label>
<input type={"radio"} name={'photo'} value={'../image2/1.jpg'} onClick={changePhoto}/> 이미지 1
</label>
<label>
<input type={"radio"} name={'photo'} value={'../image2/2.jpg'} defaultChecked onClick={changePhoto}/> 이미지 2
</label>
<label>
<input type={"radio"} name={'photo'} value={'../image2/3.jpg'} onClick={changePhoto}/> 이미지 3
</label>
<label>
<input type={"radio"} name={'photo'} value={'../image2/4.jpg'} onClick={changePhoto}/> 이미지 4
</label>
<label>
<input type={"radio"} name={'photo'} value={'../image2/5.jpg'} onClick={changePhoto}/> 이미지 5
</label>
</div>
<img src={photo}/>
</div>
);
}
export default TwoApp;
import React, {useState} from 'react';
import cat1 from '../image/21.jpg';
import cat2 from '../image/20.jpg';
import cat3 from '../image/19.jpg';
import cat4 from '../image/18.jpg';
import cat5 from '../image/17.jpg';
function ThreeApp(props) {
const [hp1,setHp1]=useState('02');
const [hp2,setHp2]=useState('0000');
const [hp3,setHp3]=useState('0000');
const [photo,setPhoto]=useState();
const changeHp1=(e)=>{
setHp1(e.target.value);
}
const changeHp2=(e)=>{
setHp2(e.target.value);
}
const changeHp3=(e)=>{
setHp3(e.target.value);
}
const changePhoto=(e)=>{
setPhoto(Number(e.target.value));
}
return (
<div>
<h3 className='alert alert-warning'>ThreeApp입니다.</h3>
<div className={'d-inline-flex'}>
<select style={{width:'100px'}} className={'form-control'} onChange={changeHp1}>
<option defaultChecked>010</option>
<option>02</option>
<option>031</option>
<option>042</option>
<option>051</option>
<option>061</option>
</select>
<b>-</b>
<input type={"text"} maxLength={4} className={'form-control'}
style={{width:'120px'}} placeholder={'0000'} onKeyUp={changeHp2}/>
{/*onChange 대신해서 onKeyUp, onKeyDown 도 가능하다.*/}
<b>-</b>
<input type={"text"} maxLength={4} className={'form-control'}
style={{width:'120px'}} placeholder={'0000'} onKeyDown={changeHp3}/>
<b>이미지 선택 :</b>
<select className={'form-control'} style={{width:'100px'}} onChange={changePhoto}>
<option value={'1'}>이미지1</option>
<option value={'2'}>이미지2</option>
<option value={'3'}>이미지3</option>
<option value={'4'}>이미지4</option>
<option value={'5'}>이미지5</option>
</select>
</div>
<br/><br/>
<hr/>
<h1>{hp1}-{hp2}-{hp3}</h1>
<img src={photo===1?cat1:photo===2?cat2:photo===3?cat3:photo===4?cat4:cat5}/>
</div>
);
}
export default ThreeApp;
var numbers=[1,2,3,4,5];
var process=numbers.map(function (num){
return num*num;
});
console.log(process);
[ 1, 4, 9, 16, 25 ]
var colors=['red','pink','yellow','gray','blue'];
console.log(colors);
colors.map((color,index)=>{
console.log(color,index);
})
[ 'red', 'pink', 'yellow', 'gray', 'blue' ]
red 0
pink 1
yellow 2
gray 3
blue 4
import React from 'react';
import Alert from '@mui/material/Alert';
import Stack from '@mui/material/Stack';
import AppleIcon from '@mui/icons-material/Apple';
function FourApp(props) {
// 배열변수 선언
const names=['뮤츠','피카츄','꼬렛','피죤','뮤','탕구리'];
// 반복문을 변수에 저장 후 출력해도 된다.
const nameList=names.map((name)=>(<li>{name}</li>));
// 색상을 5개 배열로 주시고... 결과물을 div로 출력하세요.(box 로 className 주고 할것).. 가로로 5개 쭈루룩 나오도록 해 주 세 요
const colors=['red','yellow','blue','green','orange'];
const colorClass={
width:'50px',
height:'50px',
borderRadius:'30px',
border:'1px solid gray',
marginLeft:'10px',
marginTop:'10px'
}
const colorList=colors.map((color)=>(<div style={{backgroundColor:'{color}'}}></div>));
return (
<div>
<h3 className='alert alert-secondary'>FourApp입니다.</h3>
<Stack sx={{ width: '100%' }} spacing={2}>
<Alert severity="error">배열연습</Alert>
<div>
<h3>map 연습</h3>
<ul>
{
// 반복문을 직접 리턴에 주기
names.map((name,index)=>(<b style={{marginLeft:'10px'}}>{index}:{name}</b>))
}
</ul>
<ol>
{nameList}
</ol>
</div>
</Stack>
<hr/>
<Alert severity="info"><AppleIcon/> 과제_배열색상 가로로 출력하기</Alert>
{
// colors.map((color)=>(<div className={'d-inline-flex'} style={{...colorClass,backgroundColor:color}}></div>))
colors.map((color)=>(<div className={'colorBox'} style={{backgroundColor:color}}></div>))
}
</div>
);
}
export default FourApp;
import React, {useState} from 'react';
import Alert from "@mui/material/Alert";
import ThumbUpOffAltIcon from '@mui/icons-material/ThumbUpOffAlt';
import cat4 from '../image/4.jpg';
import cat5 from '../image/5.jpg';
import cat6 from '../image/6.jpg';
import cat7 from '../image/7.jpg';
import cat8 from '../image/8.jpg';
function FiveApp(props) {
// 이미지를 배열변수에 넣기
const imgArr=[cat4,cat5,cat6,cat7,cat8];
// 이미지를 배열변수에 넣기(public)
const imgArr2=['1','2','3','4','5'];
return (
<div>
<h3 className='alert alert-danger'>FiveApp입니다.</h3>
<Alert severity="warning"><ThumbUpOffAltIcon/></Alert>
<h4>src의 이미지를 배열로 넣어 반복하기</h4>
{
imgArr.map((imgArr)=>(<img src={imgArr} style={{width:'100px'}}/>))
}
<h4>public 의 이미지를 배열로 넣어 반복하기 </h4>
{
// 예전방식
// imgArr2.map((photo)=>(<img src={'../image2/'+photo+'.jpg'} className={'photo'}/>))
// 리터럴방식
imgArr2.map((photo)=>(<img className={'photo'} src={`../image2/${photo}.jpg`}/>))
}
</div>
);
}
export default FiveApp;
// splice
const array=[1,2,3,4,5]; // 3을 제거하고 싶어요.
console.log(array);
array.splice(2,1); // 삭제할 인덱스 번호, 갯수 삭제
console.log(array);
[ 1, 2, 3, 4, 5 ]
[ 1, 2, 4, 5 ]
var array2=[1,2,3,4,5];
// 3,4 를 뽑아 출력한다.
var a2=array2.slice(2,4); // 시작인덱스, 마지막인덱스-1
// 내가 원하는 숫자보다 +1을 해서 괄호에 적는다.
// 괄호의 숫자에서 -1이 뽑힌다.
console.log(a2);
var a3=array2.slice(2,5);
console.log(a3);
var a4=array2.slice(1,4);
console.log(a4);
[ 3, 4 ]
[ 3, 4, 5 ]
[ 2, 3, 4 ]
let con=[1,2,3,4,5];
console.log(con);
[ 1, 2, 3, 4, 5 ]
let con=[1,2,3,4,5].concat([6,7],[7,8]);
console.log(con);
[
1, 2, 3, 4, 5,
6, 7, 7, 8
]
var arr=[1,2,3,4,5]; // 2를 제거하고 싶다.
console.log(arr);
var delInx=1; // 2의 인데스는 1이다.
arr=arr.filter(function (item,index){ // filter안에 인자로 함수를 받고, index만 필요하니까 명시해준다.
return index!==delInx; // 배열을 돌면서 index 1이 아닌 나머지만 다시 소집한다.
})
console.log(arr);
[ 1, 2, 3, 4, 5 ]
[ 1, 3, 4, 5 ]
<input>
태그 사용 시 value 값을 주는 순간 입력조차 불가능해진다.<input>
에 입력할 수 있도록 추가 event를 마련해줘야 한다. (onChange)import React, {useState} from 'react';
import Alert from "@mui/material/Alert";
import MoodIcon from '@mui/icons-material/Mood';
function SixApp(props) {
const [names,setNames]=useState(['피카츄','파이리','꼬부기','버터풀','야도란']);
const [irum,setIrum]=useState('');
// 추가버튼 이벤트
const btnInsert=()=>{
setNames(names.concat(irum)); // 배열에 irum 데이터 추가
setIrum(''); // 입력창 irum값 초기화
}
// Enter 이벤트
const textEnter=(e)=>{
if(e.key==='Enter'){
btnInsert();
}
}
// input창에 입력이 되도록 하는 event
const textInput=(e)=>{
setIrum(e.target.value);
}
// 더블클릭시 삭제
const dataRemove=(index)=>{
console.log("remove:"+index);
// 방법 1 : slice
// setNames([
// ...names.slice(0,index), // 0번부터 index 까지 ..
// ...names.slice(index+1,names.length)
// ]); // index번지만 빼고 잘라서 나머지를 다시 넣음.
// 방법 2 : filter
setNames(names.filter((item,i)=>i!==index))
}
return (
<div>
<h3 className='alert alert-dark'>SixApp입니다.</h3>
<Alert severity="success"><MoodIcon/></Alert>
{/*input 의 경우 value 값을 주는 순간 입력 조차 불가능해진다.*/}
<input placeholder={'이름입력'} value={irum} onChange={textInput} onKeyUp={textEnter}/>
<button type={"button"} className={'btn btn-info'} style={{marginLeft:'10px'}} onClick={btnInsert}>추가</button>
<br/>
<h4>이름을 더블클릭하면 삭제됩니다.</h4>
<ul>
{
names.map((name,index)=>(<li className={'data'} onDoubleClick={()=>dataRemove(index)}>{name}</li>))
}
</ul>
</div>
);
}
export default SixApp;
mui card 사용하기
왼쪽 카테고리에서 Card 를 찾고 원하는 카드를 찾아서 번개모양 클릭
내가 가지고 있는 코드 형태를 주의하여 복사 붙여넣기(여기서는 33번줄 제외하고 복붙)
import React, {useState} from 'react';
import { styled } from '@mui/material/styles';
import Card from '@mui/material/Card';
import CardHeader from '@mui/material/CardHeader';
import CardMedia from '@mui/material/CardMedia';
import CardContent from '@mui/material/CardContent';
import CardActions from '@mui/material/CardActions';
import Collapse from '@mui/material/Collapse';
import Avatar from '@mui/material/Avatar';
import IconButton, { IconButtonProps } from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import { red } from '@mui/material/colors';
import FavoriteIcon from '@mui/icons-material/Favorite';
import ShareIcon from '@mui/icons-material/Share';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import MoreVertIcon from '@mui/icons-material/MoreVert';
interface ExpandMoreProps extends IconButtonProps {
expand: boolean;
}
const ExpandMore = styled((props: ExpandMoreProps) => {
const { expand, ...other } = props;
return <IconButton {...other} />;
})(({ theme, expand }) => ({
transform: !expand ? 'rotate(0deg)' : 'rotate(180deg)',
marginLeft: 'auto',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
}));
function SevenApp(props) {
const [expanded, setExpanded] = React.useState(false);
const handleExpandClick = () => {
setExpanded(!expanded);
};
const [food,setFood]=useState('1');
const [text,setText]=useState('');
const selectImage=(e)=>{ // selectImage 함수는 이벤트 핸들러로 사용되며, 사용자가 셀렉트 박스에서 어떤 항목을 선택했을 때 실행됩니다.
// 'e'는 이벤트 객체로, 이벤트가 발상핸 컴포넌트와 관련된 정보를 포함합니다.
// setFood("../image2/f"+e.target.value+".jpg");
setFood(e.target.value); // 'e.target.value'는 사용자가 선택한 셀렉트 박스의 옵션 값입니다.
// 'setFood' 함수를 호출하여 'food'상태를 업데이트 합니다.
setText(e.target.options[e.target.selectedIndex].text)// 선택된 옵션의 텍스트를 가져옵니다.
// 'e.target.selectedIndex'는 사용자가 선택한 옵션의 인덱스를 나타냅니다.
console.log(food);
}
return (
<div>
<h4 className={'alert alert-info'}>SevenApp_mui 실습</h4>
<Card sx={{ maxWidth: 345 }}>
<CardHeader
avatar={
<Avatar sx={{ bgcolor: red[500] }} aria-label="recipe">
R
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={text}
subheader="September 14, 2016"
/>
<CardMedia
component="img"
height="194"
// image="/static/images/cards/paella.jpg"
// image={food}
image={`../image2/f${food}.jpg`}
alt="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="text.secondary">
This impressive paella is a perfect party dish and a fun meal to cook
together with your guests. Add 1 cup of frozen peas along with the mussels,
if you like.
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
<ExpandMore
expand={expanded}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</ExpandMore>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph>Method:</Typography>
<Typography paragraph>
Heat 1/2 cup of the broth in a pot until simmering, add saffron and set
aside for 10 minutes.
</Typography>
<Typography paragraph>
Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over
medium-high heat. Add chicken, shrimp and chorizo, and cook, stirring
occasionally until lightly browned, 6 to 8 minutes. Transfer shrimp to a
large plate and set aside, leaving chicken and chorizo in the pan. Add
pimentón, bay leaves, garlic, tomatoes, onion, salt and pepper, and cook,
stirring often until thickened and fragrant, about 10 minutes. Add
saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil.
</Typography>
<Typography paragraph>
Add rice and stir very gently to distribute. Top with artichokes and
peppers, and cook without stirring, until most of the liquid is absorbed,
15 to 18 minutes. Reduce heat to medium-low, add reserved shrimp and
mussels, tucking them down into the rice, and cook again without
stirring, until mussels have opened and rice is just tender, 5 to 7
minutes more. (Discard any mussels that don't open.)
</Typography>
<Typography>
Set aside off of the heat to let rest for 10 minutes, and then serve.
</Typography>
</CardContent>
</Collapse>
</Card>
{/* 오늘의 과제 */}
<div>
<h3>좋아하는 음식을 선택하세요</h3>
<select onChange={selectImage}>
<option value={'1'}>애그샌드위치</option>
<option value={'2'}>꼬치</option>
<option value={'3'}>매운우동</option>
<option value={'4'}>갈비찜</option>
<option value={'5'}>콘치즈</option>
<option value={'6'}>김치볶음밥</option>
<option value={'7'}>단호박밥</option>
<option value={'8'}>존맛샌드위치</option>
<option value={'9'}>연근조림</option>
<option value={'10'}>스팸마요</option>
<option value={'11'}>망고빙수</option>
<option value={'12'}>순두부라면</option>
</select>
</div>
<div>
<h3>배열 생성 후 음식이미지 선택하기</h3>
<select onChange={(e)=>{
setFood(e.target.value);
}}>
{
// 1~12 까지 반복해서 option 제공
[...new Array(12)].map((item,index)=>(<option>{index+1}</option>))
}
</select>
</div>
</div>
);
}
export default SevenApp;
오 리액트 입문 할 수 있게 됐어요 감사합니다.