스파르타 코딩클럽 - 리액트 4주차(2)

SeungMai(junior)·2021년 8월 3일
0

1. 버킷리스트에 프로그래스바 달기.

  • 모양보기

  • bucket.js

const LOAD   = 'bucket/LOAD';
const CREATE = 'bucket/CREATE';
const DELETE = "bucket/DELETE";
const UPDATE = "bucket/UPDATE";

const initialState = {
    list: [
        {text: "꽃 만들기", completed: false},
        {text: "HTML, CSS(SCSS), JS", completed: false},
        {text: "React, Vue, Angular", completed: false},
    ],
};

export const loadBucket = (bucket) => {
    return {type: LOAD, bucket};
}

export const createBucket = (bucket) => {
    return {type: CREATE, bucket}
}

export const deleteBucket = (bucket) => {
    return {type: DELETE, bucket};
}

export const updateBucket= (bucket) => {
    return {type: UPDATE, bucket};
}

export default function reducer(state = initialState, action) {
    switch (action.type) {
      case "bucket/LOAD": {
          return state;
      }

      case "bucket/CREATE": {
          const new_bucket_list = [...state.list, {text: action.bucket, completed: false}];
          return {list: new_bucket_list};
      }

      case "bucket/DELETE": {
          const bucket_list = state.list.filter((l, idx) => {
              if(idx !== action.bucket) {
                  return l;
              }
          });

          return {list: bucket_list};
      }

      case "bucket/UPDATE": {
          const bucket_list = state.list.map((l, idx) => {
              
            if(idx === action.bucket) {
                return {...l, completed: true};
            } else {
                return l;
            }
          });
          return {list: bucket_list};
      }

      default: return state;
    }
  }
  • App.js
import React from "react";
import BucketList from "./BucketList";
import styled from "styled-components";

import { withRouter } from 'react-router';
import { Route, Switch } from "react-router-dom";

import Detail from './Detail';
import NotFound from './NotFound';
import Progress from './Progress';

import { connect } from "react-redux";
import {loadBucket, createBucket} from "./redux/modules/bucket";

const mapStateToProps = (state) => {
  return {bucket_list: state.bucket.list};
}

const mapDispathchToProps = (dispatch) => {
  return {
    load: () => {
      dispatch(loadBucket());
    },

    create: (bucket) => {
      dispatch(createBucket(bucket));
    }
  };
}

// 클래스형 컴포넌트는 이렇게 생겼습니다!
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
     
    };
    this.text = React.createRef();
  }

  componentDidMount() {
    console.log(this.props);
  }

  addBucketList = () => {
    const new_item = this.text.current.value;
    this.props.create(new_item);
  };

  render() {
    return (
      <div className="App">
        <Container>
          <Title>내 버킷리스트</Title>
          <Progress/>
          <Line />
          <Switch>
            <Route path="/" exact component={BucketList} />
            <Route path="/detail/:index" component={Detail} />
            <Route component={NotFound} />
          </Switch>
        </Container>
        <Input>
          <input type="text" ref={this.text} />
          <button onClick={this.addBucketList}>추가하기</button>
        </Input>
      </div>
    );
  }
}



const Input = styled.div`
  max-width: 350px;
  min-height: 10vh;
  background-color: #fff;
  padding: 16px;
  margin: 20px auto;
  border-radius: 5px;
  border: 1px solid #ddd;
`;

const Container = styled.div`
  max-width: 350px;
  min-height: 80vh;
  background-color: #fff;
  padding: 16px;
  margin: 20px auto;
  border-radius: 5px;
  border: 1px solid #ddd;
`;

const Title = styled.h1`
  color: #e0a83f;
  text-align: center;
`;

const Line = styled.hr`
  margin: 16px 0px;
  border: 1px dotted #e0a83f;
`;

export default connect(mapStateToProps, mapDispathchToProps)(withRouter(App));
  • BucketList.js
import React from "react";
import styled from "styled-components";

import { useSelector, useDispatch } from 'react-redux';

const BucketList = (props) => {
  const bucket_list = useSelector(state => state.bucket.list);
  console.log(bucket_list);
  return (
    <ListStyle>
      {bucket_list.map((list, index) => {
        return (
          <ItemStyle
            className="list_item"
            color={list.completed? "orange" : "aliceblue"}
            key={index}
            onClick={() => {
              props.history.push("/detail/"+index);
            }}
          >
            {list.text}
          </ItemStyle>
        );
      })}
    </ListStyle>
  );
};

const ListStyle = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-x: hidden;
  overflow-y: auto;
`;

const ItemStyle = styled.div`
  padding: 16px;
  margin: 8px;
  background-color: ${(props) => props.color};
`;

export default BucketList;
  • Detail.js
import React from "react";
import { useSelector, useDispatch } from 'react-redux';
import {deleteBucket, updateBucket} from "./redux/modules/bucket";

const Detail = (props) => {
    const dispatch = useDispatch();

    const bucket_list = useSelector((state) => state.bucket.list);
    console.log(bucket_list, props);
    const bucket_index = parseInt(props.match.params.index);

    return (
        <div>
          <h1>{bucket_list[bucket_index].text}</h1>
          <button onClick={() => {
            dispatch(deleteBucket(bucket_index));
            props.history.goBack();
          }}>삭제하기</button>
          <button onClick={() => {
              dispatch(updateBucket(bucket_list));
              props.history.goBack();
          }}>완료하기</button>
        </div>
      );
    };

export default Detail;
  • Progress.js
import React from "react";
import styled from 'styled-components';

import { useSelector } from 'react-redux';

const Progress = (props) => {

    const bucket_list = useSelector(state => state.bucket.list);
    let count = 0;

    bucket_list.map((l, idx) => {
        if(l.completed) {
            count++;
        }
    });

    return (
        <ProgressBar>
            <HighLight width={(count / bucket_list.length) * 100 + "%"}></HighLight>
        </ProgressBar>
    );
}

const ProgressBar = styled.div`
    background: #eee;
    width: 100%;
    height: 40px;
`;

const HighLight = styled.div`
    background: orange;
    heigth: 40px;
    width: ${(props) => props.width};
    transition: width 1s;
`;

export default Progress;
profile
👍🏻 SeungMai (매 순간 기록을!)🧑🏻‍💻 | WIL만 올리고 있습니다 | 기술블로그는 아래 🏠 의 링크를 이용해주세요.

0개의 댓글