728x90
* 연습과제 1
import React from 'react'
import './Button.scss'
function Button({ children, size, color, width, handleClick, disabled }){
return <button
className={`Button ${size} ${color} ${width}`}
onClick={handleClick} disabled={disabled}
>{children}</button>
}
export default Button;
Button.defaultProps = {
size: 'medium',
color: 'tomato',
disabled: false
}
@use "sass:list";
$colors: blue, tomato, grey;
$hover-colors: skyblue, lightsalmon, lightgray;
$sizes: large, medium, small;
$default-height: 50px;
$default-padding-left: 10px;
$default-padding-right: 10px;
$default-font-size: 1rem;
@mixin setBtnSize($size, $h, $pl, $pr, $fs){
.#{$size}{
height: $h;
padding-left: $pl;
padding-right: $pr;
font-size: $fs;
}
}
.Button {
all: unset;
color: white;
cursor: pointer;
border-radius: 5px;
font-weight: bold;
margin-left: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
&:hover{
opacity: 0.7;
}
}
/* 버튼의 크기 설정 */
@include setBtnSize(list.nth($sizes, 1), $default-height + 20px , $default-padding-left + 5px, $default-padding-right + 5px, $default-font-size + 0.2rem);
@include setBtnSize(list.nth($sizes, 2), $default-height , $default-padding-left, $default-padding-right, $default-font-size);
@include setBtnSize(list.nth($sizes, 3), $default-height - 20px , $default-padding-left - 5px, $default-padding-right - 5px, $default-font-size - 0.2rem);
/* 버튼의 배경색 설정 */
@each $color in $colors{
.#{$color}{
background: $color;
&:hover{
background: list.nth($hover-colors, list.index($colors, $color));
}
}
}
/* 전체 너비를 차지하는 버튼 */
.fullWidth{
width: 100%;
margin-left: 0px;
margin-top: 10px;
margin-bottom: 10px;
}
* 연습과제 2
import React from 'react'
import './Modal.scss'
function Modal({ open, children }){
return <div className={`Modal ${open? "open": "close"}`}>{children}</div>
}
export default Modal;
Modal.defaultProps = {
open: false
}
$modal-func: (
open: block,
close: none
);
$modal-style: (
header: (
font-size: 1.2rem,
font-weight: bold
),
body: (
font-size: 0.9rem,
margin: 20px
),
'body input': (
width: 60%,
height: 30px,
border: 1px solid lightgray,
border-radius: 5px,
margin-bottom: 10px
),
footer: (
display: flex,
justify-content: flex-end,
align-items: center
)
);
.Modal {
width: 500px;
margin: 100px auto;
border: 1px solid tan;
padding: 10px;
text-align: center;
}
// 모달창 열고 닫기
@each $key, $value in $modal-func{
.#{$key}{
display: $value;
}
}
// 모달창 스타일링
@each $classname, $attributes in $modal-style{
.#{$classname}{
@if($classname != 'body input'){ padding: 5px; }
@each $key, $value in $attributes{
#{$key}: $value;
}
}
}
* 연습과제 3
import './App.scss';
import React, { Component } from 'react'
class App extends Component{
state = {
isSorted: false,
products: null,
sortedProducts: null
}
componentDidMount(){
const API_URL = 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline'
// 서버에서 데이터 가져오기
fetch(API_URL)
.then((res) => {
return res.json()
})
.then((products) => {
const sortedProducts = [...products] // 원본복사
sortedProducts.sort( (p1, p2) => parseFloat(p1.price) - parseFloat(p2.price) )
this.setState({products, sortedProducts})
})
}
toggleState = () => {
this.setState({ isSorted: !this.state.isSorted})
}
render(){
const { isSorted, products, sortedProducts } = this.state
const displayProducts = (product) => {
const item = (
<div key={product.id} className='product'>
<div className='product-img'><img src={product.image_link} alt={product.name}/></div>
<div className='product-name'>{product.name} (${product.price})</div>
<div className='product-description'>{product.description}</div>
<div className='product-type'>{product.product_type}</div>
</div>
)
return item
}
return (
<>
<div className="header">
<button className="sort-btns" onClick={this.toggleState}>Price</button><br/>
</div>
<div className='root'>
{isSorted ?
sortedProducts && sortedProducts.map(displayProducts)
: products && products.map(displayProducts)}
</div>
</>
)
}
}
export default App;
$primary-bg-color: peru;
$primary-color: white;
@mixin setPosition($jc, $ai, $fw){
display: flex;
flex-wrap: $fw;
justify-content: $jc;
align-items: $ai;
}
@mixin setFont($size, $weight){
font-size: $size;
font-weight: $weight;
text-align: center;
}
@mixin setSize($width, $height){
@if($width) { width: $width; }
@if($height) { height: $height; }
}
@mixin setColor($bgc, $c){
@if($bgc) { background: $bgc; }
@if($c) { color: $c; }
}
.header{
@include setSize(100%, 70px);
@include setPosition(flex-end, center, nowrap);
@include setColor($primary-color, null);
position: fixed;
left: 0;
top: 0;
right: 0;
box-shadow: 1px 1px 5px 5px darkgray;
z-index: 1;
.sort-btns{
all: unset;
@include setSize(100px, 50px);
@include setFont(1rem, bold);
@include setColor($primary-bg-color, $primary-color);
border-radius: 10px;
cursor: pointer;
margin-right: 10px;
&:hover{
opacity: 0.8;
}
}
}
.root{
@include setSize(60%, null);
@include setPosition(center, center, wrap);
margin: 100px auto;
.product{
@include setSize(null, 500px);
@include setColor($primary-bg-color, $primary-color);
flex: 200px;
box-shadow: 1px 1px 5px 5px $primary-bg-color;
margin: 10px;
overflow: hidden;
.product-img{
@include setSize(100%, 180px);
overflow: hidden;
img{
@include setSize(100%, 100%);
}
}
.product-name{
@include setFont(1.1rem, bold);
}
.product-description{
@include setFont(0.9rem, 400);
margin-top: 15px;
}
}
}
728x90
'프론트엔드 > React 연습과제 해답' 카테고리의 다른 글
리액트 기초이론 7 - 이벤트(Event) 처리하기 해답 (0) | 2022.03.09 |
---|---|
리액트 기초이론 5 - 컴포넌트 스타일링 3 - Styled Components 해답 (0) | 2022.03.07 |
리액트 기초이론 5 - 컴포넌트 스타일링 해답 (0) | 2022.02.28 |
리액트 기초이론 4 - 컴포넌트의 생명주기 (Life cycle) 해답 (0) | 2022.02.23 |
리액트 기초이론 3 - JSX 문법 해답 (0) | 2022.02.21 |