mui 쓰는 법

  1. 터미널을 통해 해당 react-project directory로 진입한다.
  2. mui.com 에 접속한다.
  3. installation 을 검색한다.
  4. 아래 4가지 명령어를 터미널에 입력한다. (mui 관련 사항들을 다운로드 받는거다.)
  5. 역시나 npm, yarn 중에서 골라서 입력하면 된다.
  • yarn
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
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

mui icon 쓰는 법

  1. Material Icons 를 검색한다.
  2. 마음에 드는 icon을 선택한다.
  3. 아래 그림과 같이 해당 icon을 import 받아서 사용하면 된다.

폴더트리

index.js

  • App 하나만 import 받아 출력할 예정이며, 화면에 표시할 사항을 App.js에 모두 배치할 것이다.
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();

App.js

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.css

.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;
}

OneApp.js

  • javascript 문법 사용 가능하다.
  • if 조건문을 이용해서 숫자 제한두기
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;

TwoApp.js

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>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <label>
                    <input type={"radio"} name={'photo'} value={'../image2/1.jpg'} onClick={changePhoto}/> 이미지 1
                </label>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <label>
                    <input type={"radio"} name={'photo'} value={'../image2/2.jpg'} defaultChecked onClick={changePhoto}/> 이미지 2
                </label>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <label>
                    <input type={"radio"} name={'photo'} value={'../image2/3.jpg'} onClick={changePhoto}/> 이미지 3
                </label>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <label>
                    <input type={"radio"} name={'photo'} value={'../image2/4.jpg'} onClick={changePhoto}/> 이미지 4
                </label>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <label>
                    <input type={"radio"} name={'photo'} value={'../image2/5.jpg'} onClick={changePhoto}/> 이미지 5
                </label>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            </div>

            <img src={photo}/>

        </div>
    );
}

export default TwoApp;

ThreeApp.js

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>
                &nbsp;&nbsp;<b>-</b>&nbsp;&nbsp;
                <input type={"text"} maxLength={4} className={'form-control'}
                       style={{width:'120px'}} placeholder={'0000'} onKeyUp={changeHp2}/>
                {/*onChange 대신해서 onKeyUp, onKeyDown 도 가능하다.*/}
                &nbsp;&nbsp;<b>-</b>&nbsp;&nbsp;
                <input type={"text"} maxLength={4} className={'form-control'}
                       style={{width:'120px'}} placeholder={'0000'} onKeyDown={changeHp3}/>
                &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                <b>이미지 선택 :</b>&nbsp;&nbsp;
                <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;


틈새 map 기본 예제

  • map : 반복되는 컴포넌트를 렌더링하기 위하여 자바스크립트 배열의 내장 함수인 map()을 사용 한다.
  • 파라미터로 전달된 함수를 사용하여 뱅려 내 각 요소를 원하는 규칙에 따라 변환한 후 새로운 배열을 생성 한다.

map문법

  • arr.map(callbackFunction,[thisArg])
  • arr.map(callbackFunction(currenValue,index,arry),thisArg)
  1. callbackFunction : 새로운 배열의 요소를 생성하는 함수로서 다음 세가지 인수를 갖는다.
    • currenValue : 현재 배열(arr) 내의 값들을 의미
    • index : 현재 배열 내 값의 인덱스를 의미
    • array : 현재 배열
  2. thisArg(선택항목) : callback 함수 내부에서 사용할 this 레퍼런스 를 설정한다.
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

FourApp.js

  • material icon 사용하기
  • map 사용하기
  • 'colorBox' 클래스는 app.css 에 작성한거다.
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;

FiveApp.js

  • 이미지를 변수로 반복하기
  • 출력시에 편의성을 위해 백틱 `` 사용하기
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, ,slice, concat, filter

splice

  • splice는 지정된 배열에 해당 인덱스의 숫자를 삭제할 경우
  • .splice(시작인덱스번호,삭제할갯수)
// 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 ]

slice

  • slice는 원본 배열을 건드리지 않고, 수정된복사 배열값을 리턴한다.(교체는 안된다.)
  • .slice(시작인덱스,마지막인덱스+1)
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 ]

Arrays.concat(value)

  • concat 메서드는 원하는 값을 원본 배열의 끝에 추가한 다음, 새로운 배열을 만든다.
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
]

filter

  • 원본 배열을 수정하는 함수를 적용한다.
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 ]

SixApp.js

  • 배열 정리하기
  • enter 기능 적용하기
  • 더블클릭 적용하기
  • <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;

SevenApp.js

  • mui card 사용하기

  • 왼쪽 카테고리에서 Card 를 찾고 원하는 카드를 찾아서 번개모양 클릭

  • 내가 가지고 있는 코드 형태를 주의하여 복사 붙여넣기(여기서는 33번줄 제외하고 복붙)

  • title, image 등 내가 수정할 곳 찾아서 수정하기
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&apos;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;

profile
java를 잡아...... 하... 이게 맞나...

1개의 댓글

comment-user-thumbnail
2023년 12월 11일

오 리액트 입문 할 수 있게 됐어요 감사합니다.

답글 달기