오늘은 todoList를 만들어보겠습니다.
목차 | |
1. | todoList |
2. | axios |
3. | 느낀 점 |
1. todoList
- App.js
import './App.css';
import TodoList from './component/TodoList';
import './component/createTodo.css';
function App() {
return (
<div className="App">
<div className='title'>TodoList</div>
<TodoList />
</div>
);
}
export default App;
- Todo.jsx
import React from 'react';
import './createTodo.css';
const Todo = ({ user, onRemove, onToggle }) => {
return (
<div className='TodoContainer'>
<div className='TodoBody'>
<span className='TodoUser' style={{
cursor: 'pointer',
textDecorationLine: user.active ? 'line-through' : 'none'
}} onClick={() => onToggle(user.id)}> {user.username}</span>
</div>
<button className='delButton' onClick={() => onRemove(user.id)}>X</button>
</div>
);
};
export default Todo;
- CreateTodo.jsx
import React from 'react';
import './createTodo.css';
const CreateTodo = ({ username, onChange, onCreate }) => {
return (
<div className='createName'>
<input
className='todoInput'
type="text"
name='username'
onChange={onChange}
value={username}
/>
<button className='createButton' onClick={onCreate}>create</button>
</div>
);
};
export default CreateTodo;
- TodoList.jsx
import React, { useRef, useState } from 'react';
import Todo from './Todo';
import CreateTodo from './CreateTodo';
import './createTodo.css';
const TodoList = () => {
const nextId = useRef(1);
const [users, setUsers] = useState([]);
const [ inputs, setInputs ] = useState({
username : '',
});
const { username } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]:value
});
console.log(inputs);
}
const onCreate = ()=>{
const user = {
id: nextId.current,
username: username,
}
setUsers(users.concat(user));
setInputs({
username:'',
})
nextId.current += 1 ;
console.log(users);
}
const onRemove = (id) => {
setUsers(users.filter(user => user.id !== id));
}
const onToggle = (id) => {
setUsers(users.map(u=>
u.id === id ? { ...u, active: !u.active} : u
))
}
return (
<div className='userList'>
<CreateTodo username={username} onChange={onChange} onCreate={onCreate}/>
{
users.map((u)=>(
<Todo user={u} key={u.id} onRemove={onRemove} onToggle={onToggle}/>
))
}
</div>
);
};
export default TodoList;
- createTodo.css
.App{
width: 1000px;
margin: 0 auto;
}
.title{
font-size: 70px;
font-weight: 700;
/* color 그라데이션 */
background: linear-gradient(to right top, #861657, #ffa69e);
color: transparent;
-webkit-background-clip: text;
margin-bottom: 30px;
}
.createName{
width: 700px;
height: 100px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
/* background-color: rgba(128, 128, 128, 0.075); */
border-radius: 15px;
}
.todoInput{
width: 250px;
height: 35px;
margin-right: 30px;
color: purple;
font-size: 25px;
font-weight: 550;
outline: none;
/* border 그라데이션 */
border: 2px solid transparent;
border-radius: 15px;
background-image: linear-gradient(#fff, #fff), linear-gradient(to right top, #861657, #ffa69e);
background-origin: border-box;
background-clip: content-box, border-box;
}
.createButton{
width: 100px;
height: 40px;
color: white;
font-size: 20px;
font-weight: 300;
/* border 그라데이션 - button */
border: 1px solid transparent;
border-radius: 20px;
background-image: linear-gradient(to right top, #12c2e9, #c471ed, #f64f59);
background-origin: border-box;
background-clip: content-box, border-box;
}
.createButton:hover{
cursor: pointer;
}
.TodoUser{
font-size: 30px;
font-weight: 550;
}
.TodoContainer{
margin: 30px auto;
display: flex;
justify-content: center;
align-items: center;
width: 550px;
height: 80px;
/* border 그라데이션 */
border: 8px solid transparent;
border-radius: 15px;
background-image: linear-gradient(#fff, #fff), linear-gradient(to right top, #861657, #ffa69e);
background-origin: border-box;
background-clip: content-box, border-box;
}
.TodoContainer:nth-child(2n){
/* border 그라데이션 */
border: 8px solid transparent;
border-radius: 15px;
background-image: linear-gradient(#fff, #fff), linear-gradient(to left top, #861657, #ffa69e);
background-origin: border-box;
background-clip: content-box, border-box;
}
.TodoBody{
width: 300px;
height: 50px;
border-radius: 10px;
padding-left: 10px;
display: flex;
align-items: center;
margin-right: 100px;
color: #861657;
}
.delButton{
width: 70px;
height: 55px;
font-size: 25px;
font-weight: 550;
border: 5px solid white;
border-radius: 20px;
/* color 그라데이션 */
background: linear-gradient(to right top, #861657, #ffa69e);
color: transparent;
-webkit-background-clip: text;
}
.delButton:hover{
width: 70px;
height: 50px;
color: white;
/* border 그라데이션 - button */
border: 1px solid transparent;
border-radius: 20px;
background-image: linear-gradient(to right top, #12c2e9, #c471ed, #f64f59);
background-origin: border-box;
background-clip: content-box, border-box;
}
▷ 출력
2. axios
◈ useMemo
useMemo() => 리액트에서 컴포넌트 성능을 최적화 하는데 사용되는 훅
memo => memoization의 약자. 메모리에 넣기
동일한 계산을 반복해야 할 떄, 이전에 값을 메모리에 저장함으로써
반복수행을 제거하여 프로그램 실행 속도를 빠르게 해주는 기술
함수형 컴포넌트가 랜더링 => 컴포넌트 함수 호출 => 모든 내부 변수 초기화
useMemo 랜더링 => 함수 호출 => memoize된 함수를 재사용
◈ axios
■ axios(외장 라이브러리 별도 설치 필요)
=> js ajax(js 내장 라이브러리)
- url : 요청 주소
- method : get(요청), post(삽입), put 또는 patch(수정), delete(삭제)
response : 응답 객체
request : 요청 객체
axios.get( url [, config] )
axios.post( url [, config] [, data] )
axios.put( url [, config] [, data] )
axios.delete( url [, config] )
■ useEffect() : hook
- 컴포넌트가 랜더링 될 때, 혹은 업데이트 될 때 실행되는 hook
useEffect((function), deps)
- function : 실행시킬 함수
- deps : 배열형태
- [] 빈배열 : 마운트 될 때만 실행
- x : 매번 랜더링 될 때마다 실행
- [name] : 업데이트 될 때마다 실행
▶ 입력
npx create-react-app axios-app
cd axios-app
npm i axios (=> axios 설치)
※ jsonplaceholder
https://jsonplaceholder.typicode.com/users
- App.js
import './App.css';
import User from './component/User';
function App() {
return (
<div className="App">
<User />
</div>
);
}
export default App;
- User.jsx
import React from 'react';
import { useState } from 'react';
// import { useEffect } from 'react';
import axios from 'axios';
const User = () => {
const [ users, setUsers ] = useState([]);
// 다운로드가 잘 되었는지 확인용 / 에러 확인용
const [ loading, setLoading ] = useState(false);
const [ error, setError ] = useState(null);
const fetchUsers = async () => {
try{
// 요청이 시작되면 loading의 상태를 true로 변경
setLoading(true);
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
console.log(response);
setUsers(response.data); // data는 response.data 안에 담겨있음.
}catch(e){
setError(e);
}
setLoading(false);
}
// useEffect(() => {
// fetchUsers();
// },[]);
if(loading) return <div>로딩중...</div>;
if(error) return <div>에러가 발생했습니다.</div>
// if(!users) return <div>User null!!!</div>
return (
<div className='user'>
<div>User.jsx 영역</div>
<ul>
{
users.map(user => (
<li key={user.id}>{user.username} ({user.name})</li>
))
}
</ul>
{/* button을 추가하여 클릭시 user 데이터가 뜰 수 있도록 설정 */}
<button onClick={fetchUsers}>데이터 불러오기</button>
</div>
);
};
export default User;
▷ 출력
3. 느낀 점
예전에 css를 했을 때에는 정말 하기 싫었는데.. 오랜만에 해보니 너무 재미있어서 기분이 좋았다. 다른 수강생분들이 하신 todoList를 보면서 내가 어떤 기능을 새로 추가할 수 있을지 고민해봐야할 것 같다는 생각을 하게 되었다.
'Front-end > React' 카테고리의 다른 글
React 기초(db 연동)- AWS 풀스택 과정 42일차 (0) | 2024.09.19 |
---|---|
React 기초(useReducer)- AWS 풀스택 과정 41일차 (0) | 2024.09.10 |
React 기초(배열)- AWS 풀스택 과정 39일차 (0) | 2024.09.06 |
React 기초(input, param)- AWS 풀스택 과정 38일차 (0) | 2024.09.05 |
React 설정 및 기초- AWS 풀스택 과정 37일차 (4) | 2024.09.04 |