Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- getday()
- React
- isNaN()
- 교집합
- setDate
- map()
- 차집합
- substring()
- indexOf()
- 항해99솔직후기 #항해99장점 #항해99단점 #부트캠프추천
- reat if문
- Math.sqrt()
- toUpperCase()
- new Date()
- Eventlitener
- repeat()
- Math.floor()
- jsx반복문
- useRef()
- 3진수
- useEffect()
- slice()
- includes()
- sort()
- filter()
- parseInt()
- charAt()
- 소수점 올림내림
- useState()
- Number()
Archives
- Today
- Total
개발자로 전향중
리액트 3주차 버킷리스트 만들기 연습 2022-01-25 본문
My bucketlist!
설치 프로그램 styled.component, router,
App.js
import { Route, Routes } from "react-router-dom";
import React from "react";
// BucketList 컴포넌트를 import 해옵니다.
// import [컴포넌트 명] from [컴포넌트가 있는 파일경로];
import BucketList from "./BucketList";
import styled from "styled-components";
import Detail from "./detail";
import {useDispatch} from "react-redux";
import {createBucket} from "./redux/modules/bucket"
import Progress from "./Progress";
function App() {
// const [list, setList] = React.useState(["영화관 가기", "매일 책읽기", "수영 배우기"]);
// 상태값이 동적으로 바뀔경우 hook usestate const [상태 값 저장 변수, 상태 값 갱신함수] = useState[상태초기값]
const text = React.useRef(null);
// const navigate = useNavigate();
const dispatch = useDispatch();
const addBucketList = () => {
// 스프레드 문법! 기억하고 계신가요? :)
// 원본 배열 list에 새로운 요소를 추가해주었습니다.
// setList([...list, text.current.value]);
dispatch(createBucket({text: text.current.value, completed: false}));
};
return (
<div className="App">
<Container>
<Title>내 버킷리스트</Title>
<Progress/>
<Line />
{/* 컴포넌트를 넣어줍니다. */}
{/* <컴포넌트 명 [props 명]={넘겨줄 것(리스트, 문자열, 숫자, ...)}/> */}
<Routes>
<Route path="/" element={<BucketList />} />
<Route path="/detail:index" element={<Detail />} />
</Routes>
</Container>
{/* 인풋박스와 추가하기 버튼을 넣어줬어요. */}
<Input>
<input type="text" ref={text} />
<button onClick={addBucketList}>추가하기</button>
</Input>
<button onClick={() => {
window.scrollTo({top:0, left:0, behavior: "smooth"});
}}>위로 가기</button>
</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;
display: flex;
& > * {
padding : 5px;
}
& input{
border: 1px solid #888;
width: 70%;
margin-right: 10px;
}
& input:focus {
border: 1px solid #a673ff;
outline: none;
}
& button {
width: 25%;
color: #fff;
border: #a673ff;
background: #a673ff;
}
`;
const Container = styled.div`
max-width: 350px;
min-height: 60vh;
background-color: #fff;
padding: 16px;
margin: 20px auto;
border-radius: 5px;
border: 1px solid #ddd;
`;
const Title = styled.h1`
color: slateblue;
text-align: center;
`;
const Line = styled.hr`
margin: 16px 0px;
border: 1px dotted #ddd;
`;
export default App;
BucketList.js
// 리액트 패키지를 불러옵니다.
import React from "react";
import styled from "styled-components";
import { useNavigate } from "react-router-dom";
import {useSelector} from "react-redux"
const BucketList = (props) => {
let navigate = useNavigate();
// const my_lists = props.list;
const my_lists = useSelector((state) => state.bucket.list);
return (
<ListStyle>
{my_lists.map((list, index) => {
return (
<ItemStyle
completed={list.completed}
className="list_item"
key={index}
onClick={() => {
navigate("/detail"+index);
}}
>
{list.text}
</ItemStyle>
);
})}
</ListStyle>
);
};
const ListStyle = styled.div`
display: flex;
flex-direction: column;
height: 50vh;
overflow-x: hidden;
overflow-y: auto;
max-height: 50vh;
`;
const ItemStyle = styled.div`
padding: 16px;
margin: 8px;
color: ${(props) => props.completed? "#fff": "#333"};
background-color: ${(props) => (props.completed ? "#673ab7" : "aliceblue")};
`;
export default BucketList;
detail.js
// 리액트 패키지를 불러옵니다.
import React from "react";
import { useNavigate } from "react-router-dom";
import { useParams } from "react-router-dom";
import { useSelector } from "react-redux"
// 데이터가져올때
import { useDispatch } from "react-redux";
import { deleteBucket, updateBucket } from "./redux/modules/bucket";
const Detail = (props) => {
const dispatch = useDispatch();
let navigate = useNavigate();
const params = useParams();
const bucket_index = params.index;
const bucket_list = useSelector((state) => state.bucket.list);
return (
<div>
<h1 onClick={() => {
navigate("/")
}}>{bucket_list[bucket_index].text}</h1>
<button onClick={() => {
dispatch(updateBucket(bucket_index));
navigate("/")
}}>완료하기</button>
<button onClick={() => {
dispatch(deleteBucket(bucket_index));
navigate("/")
}}>삭제하기</button>
</div>
)
};
export default Detail;
projess.js
import React from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
const Progress = () => {
const bucket_list = useSelector((state) => state.bucket.list)
console.log(bucket_list)
let count = 0;
bucket_list.map((b, idx) => {
if (b.completed) {
count++;
}
})
return (
<ProgressBar>
<HighLight width={(count/bucket_list.length) * 100 + "%"} />
<Dot/>
</ProgressBar>
)
}
const ProgressBar = styled.div`
background: #eee;
width: 100%;
height: 20px;
display: flex;
align-items: center;
border-radius: 10px;
`;
// display는 하이라이라트와 닷을 겹치게 하기위해
const HighLight = styled.div`
background: #673ab7;
transition: 1s;
width: ${(props) => props.width};
height: 20px;
border-radius: 10px;
`;
const Dot = styled.div`
width: 40px;
height: 40px;
background: #fff;
border: 5px solid #673ab7;
border-radius: 40px;
margin-left: -20px;
`;
export default Progress;
.redux/modules/bucket.js
// 액션 타입을 정해줍니다.
const CREATE = "bucket/CREATE";
const DELETE = "bucket/DELETE";
const UPDATE = "bucket/UPDATE";
// 초기 상태값을 만들어줍니다.
const initialState = {
list: [
{text: "영화관 가기", completed: false},
{text: "매일 책읽기", completed: false},
{text: "수영 배우기", completed: false},
{text: "코딩하기", completed: false},
],
// list: ["영화관 가기", "매일 책읽기", "수영 배우기"],
};
// 액션 생성 함수예요.
// 액션을 만들어줄 함수죠!
export function createBucket(bucket) {
console.log("액션을 생성할거야!");
return { type: CREATE, bucket: bucket };
}
export function updateBucket(bucket_index) {
return { type: UPDATE, bucket_index };
}
export function deleteBucket(bucket_index) {
console.log("지울 버킷 인덱스", bucket_index);
return { type: DELETE, bucket_index };
}
// 리듀서예요.
// 실질적으로 store에 들어가 있는 데이터를 변경하는 곳이죠!
export default function reducer(state = initialState, action = {}) {
switch (action.type) {
case "bucket/CREATE": {
console.log("이제 값을 바꿀거야!");
const new_bucket_list = [...state.list, action.bucket];
return { list: new_bucket_list };
}
case "bucket/UPDATE": {
const new_bucket_list = state.list.map((l, idx) => {
if(parseInt(action.bucket_index) === idx) {
return {...l, completed: true};
} else {
return l
}
})
return {list: new_bucket_list}
}
case "bucket/DELETE": {
const new_bucket_list = state.list.filter((l, idx) => {
return parseInt(action.bucket_index) !== idx;
});
return { list: new_bucket_list };
}
default:
return state;
}
}
.redux/configStore.js
//configStore.js
import { createStore, combineReducers } from "redux";
import bucket from "./modules/bucket";
// root 리듀서를 만들어줍니다.
// 나중에 리듀서를 여러개 만들게 되면 여기에 하나씩 추가해주는 거예요!
const rootReducer = combineReducers({ bucket });
// 스토어를 만듭니다.
const store = createStore(rootReducer);
export default store;
'React' 카테고리의 다른 글
React 패키지 설치 (0) | 2022.01.27 |
---|---|
리액트 3주차 버킷리스트 만들기 연습 2022-01-26 (0) | 2022.01.26 |
리액트 3주차 평점 만들기 개인과제 2022-01-24 진행상황 (0) | 2022.01.24 |
리액트 3주차 개인과제 2022-01-23 진행상황 (0) | 2022.01.23 |
꼭 알고 있어야 할 react 문법! (0) | 2022.01.23 |