React
[TIL/React] 2023/06/29
ㅈ
2023년 6월 29일3min read
Home.js
code
import React, { forwardRef, useEffect } from "react";
import { styled } from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import { getTodo } from "../features/todosSlice";
const HomeContainer = styled.div`
height: 100%;
background-image: url("https://kormedi.com/wp-content/uploads/2021/10/211025_02_01-580x410.jpg");
background-position: top center;
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
`;
const Home = forwardRef((props, ref) => {
return <HomeContainer ref={ref}></HomeContainer>;
});
export default Home;
AddTask.js
code
import React, { forwardRef, useEffect } from "react";
import { useState } from "react";
import { useDispatch } from "react-redux";
import { styled } from "styled-components";
import { addTodo } from "../features/todosSlice";
import { getTodo } from "../features/todosSlice";
const inputArray = ["Title", "Subtitle", "Desc"];
const AddTaskFieldWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
background-color: #f1e3d9;
`;
const AddTaskContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 70%;
`;
const AddTaskTitle = styled.h1`
margin-bottom: 100px;
font-weight: bolder;
font-size: 70px;
`;
const AddTaskInput = styled.input`
padding: 40px;
border: 1px solid #ccc;
border-radius: 10px;
width: 65%;
margin-bottom: 20px;
`;
const AddTaskButton = styled.button`
padding: 20px 30px;
background-color: #c07848;
font-weight: bolder;
color: #fff;
border: none;
border-radius: 4px;
margin-top: 100px;
cursor: pointer;
width: 40%;
&:hover {
opacity: 0.7;
}
`;
const AddTask = forwardRef((props, ref) => {
const dispatch = useDispatch();
const [inputValue, setInputValue] = useState({
Title: "",
Subtitle: "",
Desc: "",
isDone: false,
id: Date.now(),
});
const handleInputValue = (event) => {
const { value, name } = event?.target;
setInputValue((prev) => {
return { ...prev, [name]: value };
});
};
const handleAddClick = () => {
dispatch(addTodo(inputValue));
setInputValue({
Title: "",
Subtitle: "",
Desc: "",
isDone: false,
id: Date.now(),
});
};
console.log(inputValue);
return (
<AddTaskFieldWrapper ref={ref}>
<AddTaskContainer>
<AddTaskTitle>ADD TASK</AddTaskTitle>
{inputArray?.map((elem, idx) => (
<AddTaskInput
key={idx}
name={elem}
value={inputValue?.[elem]}
onChange={handleInputValue}
placeholder={`Add your ${elem}!`}
/>
))}
<AddTaskButton onClick={handleAddClick}>ADD</AddTaskButton>
</AddTaskContainer>
</AddTaskFieldWrapper>
);
});
export default AddTask;
RecentTodo.js
code
import React, { forwardRef } from "react";
import { useSelector } from "react-redux";
import styled from "styled-components";
const RecentTodoFieldWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
width: 100%;
`;
const RecentTodoContainer = styled.div`
display: flex;
justify-content: space-around;
align-items: center;
width: 70%;
height: 50%;
border: none;
border-radius: 10px;
background-color: #f1e3d9;
`;
const RecentTodoAreaTitle = styled.h1`
margin-bottom: 100px;
font-weight: bolder;
font-size: 70px;
`;
const RecentTodoTitleWrapper = styled.div`
border-bottom: 6px solid #c07848;
`;
const RecentTodoMainWrapper = styled.div`
border: 1px solid black;
display: flex;
flex-direction: column;
row-gap: 100px;
justify-content: center;
align-items: center;
`;
const RecentTodoTitle = styled.p`
font-size: 30px;
font-weight: bolder;
`;
const RecentTodoSubtitle = styled.p`
font-size: 20px;
`;
const RecentTodoDesc = styled.p`
font-size: 20px;
`;
const RecentTodo = forwardRef((props, ref) => {
const { todo } = useSelector((state) => state.todos);
console.log(todo);
const mostRecentTodo = todo.length >= 0 ? todo[todo.length - 1] : null;
return (
<RecentTodoFieldWrapper ref={ref}>
<RecentTodoAreaTitle>Recent Todo</RecentTodoAreaTitle>
<RecentTodoContainer>
<RecentTodoTitleWrapper>
<RecentTodoTitle>{mostRecentTodo?.Title}</RecentTodoTitle>
</RecentTodoTitleWrapper>
<RecentTodoMainWrapper>
<div>
<RecentTodoSubtitle>{mostRecentTodo?.Subtitle}</RecentTodoSubtitle>
<RecentTodoDesc>{mostRecentTodo?.Desc}</RecentTodoDesc>
</div>
<div>
<button>COMPLETE</button>
<button>DELETE</button>
</div>
</RecentTodoMainWrapper>
</RecentTodoContainer>
</RecentTodoFieldWrapper>
);
});
export default RecentTodo;
MyTodo.js
code
import React, { forwardRef } from "react";
import { styled } from "styled-components";
import { useSelector } from "react-redux";
const MyTodoFieldWrapper = styled.div`
display: flex;
justify-content: space-around;
align-items: center;
height: 100%;
width: 100%;
background-color: #f1e3d9;
overflow-x: auto;
column-gap: 10px;
`;
const TodoCard = styled.div`
display: flex;
flex-direction: column;
width: 2000px;
height: 70%;
background-color: #fff;
border: none;
border-radius: 10px;
`;
const MyTodo = forwardRef((props, ref) => {
const { todo } = useSelector((state) => state.todos);
console.log(todo);
return (
<MyTodoFieldWrapper ref={ref}>
{todo.map((elem, idx) => {
console.log(elem);
return (
<TodoCard key={idx}>
<p>{elem.Title}</p>
<p>{elem.Subtitle}</p>
<p>{elem.Desc}</p>
</TodoCard>
);
})}
</MyTodoFieldWrapper>
);
});
export default MyTodo;
어쩌구저쩌구
MyTodo 컴포넌트에서, todo card에 overflow-x를 적용하는 것이 목표였는데... 왜왜왜 후
More to read
REST API
프론트엔드와 백엔드 사이
HTTP 상태 코드는 프론트엔드에서 백엔드로 보냈던 요청의 수행 결과를 의미하는 일종의 약속이며, API를 구성하는 핵심 요소 중 하나입니다. 상태 코드와 관련하여, 백엔드는 잘 모르는 프론트엔드의 슬픈 사정이 있습니다.아래는 요청이 실패했음에도, 백엔드에서 상태 코드
JWT토큰 관리 방식 톺아보기
0. 들어가며 🎯 서비스에 접근하려는 사용자가 누구인지 확인하는 과정을 사용자 인증이라고 합니다. 인증된 사용자에게 주어진 권한을 확인하는 작업은 인가라고 부릅니다. 이번 글에서는 인가는 다루지 않습니다. 사용자 인증에는 많은 방식이 있지만, 오늘은 세션 인증 방
A2AA2A / MCP 멀티 에이전트 오케스트레이션
0. 들어가며 ✍️ Google for Developers에, 레스토랑 공급망 시나리오로 엮은 6대 프로토콜(MCP, A2A, UCP, AP2, A2UI, AG-UI)에 대한 가이드가 게시된 이후, MCP와 A2A부터 구현해 보는 것이 좋을 것 같다는 생각이 들었습니