728x90
create-react-app환경에서
저번에 만든 튕기는공과 material-ui의 Sign, Album 페이지를 라우팅 해보기로 한다.
@material-ui/core, @material-ui/icons, react-router-dom을 npm으로 설치해준다.
material-ui에서 제공하는 template에서 Album과 Sign을 가져온다
https://material-ui.com/getting-started/templates/
Album.js
import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Button from '@material-ui/core/Button';
import CameraIcon from '@material-ui/icons/PhotoCamera';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import CssBaseline from '@material-ui/core/CssBaseline';
import Grid from '@material-ui/core/Grid';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
import Link from '@material-ui/core/Link';
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
icon: {
marginRight: theme.spacing(2),
},
heroContent: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(8, 0, 6),
},
heroButtons: {
marginTop: theme.spacing(4),
},
cardGrid: {
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8),
},
card: {
height: '100%',
display: 'flex',
flexDirection: 'column',
},
cardMedia: {
paddingTop: '56.25%', // 16:9
},
cardContent: {
flexGrow: 1,
},
footer: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(6),
},
}));
const cards = [1, 2, 3, 4, 5, 6, 7, 8, 9];
export default function Album() {
const classes = useStyles();
return (
<React.Fragment>
<CssBaseline />
<AppBar position="relative">
<Toolbar>
<CameraIcon className={classes.icon} />
<Typography variant="h6" color="inherit" noWrap>
Album layout
</Typography>
</Toolbar>
</AppBar>
<main>
{/* Hero unit */}
<div className={classes.heroContent}>
<Container maxWidth="sm">
<Typography component="h1" variant="h2" align="center" color="textPrimary" gutterBottom>
Album layout
</Typography>
<Typography variant="h5" align="center" color="textSecondary" paragraph>
Something short and leading about the collection below—its contents, the creator, etc.
Make it short and sweet, but not too short so folks don't simply skip over it
entirely.
</Typography>
<div className={classes.heroButtons}>
<Grid container spacing={2} justify="center">
<Grid item>
<Button variant="contained" color="primary">
Main call to action
</Button>
</Grid>
<Grid item>
<Button variant="outlined" color="primary">
Secondary action
</Button>
</Grid>
</Grid>
</div>
</Container>
</div>
<Container className={classes.cardGrid} maxWidth="md">
{/* End hero unit */}
<Grid container spacing={4}>
{cards.map((card) => (
<Grid item key={card} xs={12} sm={6} md={4}>
<Card className={classes.card}>
<CardMedia
className={classes.cardMedia}
image="https://source.unsplash.com/random"
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
Heading
</Typography>
<Typography>
This is a media card. You can use this section to describe the content.
</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
View
</Button>
<Button size="small" color="primary">
Edit
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</main>
{/* Footer */}
<footer className={classes.footer}>
<Typography variant="h6" align="center" gutterBottom>
Footer
</Typography>
<Typography variant="subtitle1" align="center" color="textSecondary" component="p">
Something here to give the footer a purpose!
</Typography>
<Copyright />
</footer>
{/* End footer */}
</React.Fragment>
);
}
Sign.js
import React from 'react';
import Avatar from '@material-ui/core/Avatar';
import Button from '@material-ui/core/Button';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import Link from '@material-ui/core/Link';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
export default function SignIn() {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}>
<Copyright />
</Box>
</Container>
);
}
Ball은 전에 작성한 포스트에 있다.
Router.js
import React from 'react';
import {Route} from 'react-router-dom';
import Album from './components/Album';
import Sign from './components/Sign';
import Ball from './Ball';
class Router extends React.Component {
render(){
return (
<div>
<Route exact path="/" component={Sign}/>
<Route path="/Album" component={Album}/>
<Route path="/Ball" component={Ball}/>
</div>
);
}
}
export default Router;
<Route exact path:"/" conponent={Sign}/>에서 exact가 붙으면 path의 경로와 정확히 일치해야 라우팅이 된다.
만약에, "/" 경로에 exact를 하지않으면 그 밑의 "/Album", "/Ball"에도 "/"가 포함되어있어 {Sign}이 같이 렌더링된다
Root.js
import React from 'react';
import {BrowserRouter} from 'react-router-dom';
import Router from './Router';
const Root = () => (
<BrowserRouter>
<Router/>
</BrowserRouter>
);
export default Root;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
import Root from './Root';
// ReactDOM.render(
// <Ball />,
// document.getElementById('root')
// );
ReactDOM.render(
<Root />,
document.getElementById('root')
);
// 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();
index.js에서 Root를 import해서 렌더링한다.
라우팅할때 구조는
<BrowserRouter>
<Route path="~~~" component=~~~ />
...
</BrowserRouter>
형식으로 BrowserRouter 안에 Route들로 구성되야 작동하는듯 하다. Route만 사용했을때는 작동되지않았다.
http://localhost:3000/
http://localhost:3000/album
http://localhost:3000/ball
라우팅 잘된다.
"/" Route에 exact를 안하면
이렇게 같이 렌더링된다.
출처 : material-ui, velopert
728x90
'React' 카테고리의 다른 글
카카오 맵 javascript api 적용하기 - 키워드 검색 (5) | 2021.09.14 |
---|---|
카카오 맵 javascript api 적용하기 - 주소로 위치 표시 (0) | 2021.09.14 |
리액트 react-device-detect로 디바이스 구분하기 (0) | 2021.09.10 |
React 스크롤 페이징 구현 react-intersection-observer (0) | 2021.08.28 |
카카오 로그인 구현 javascript (0) | 2021.08.20 |