본문 바로가기

React 수업 정리

React 4일차.

3일차에 했던 유저리스트에 눌러서 액티브가 true인 유저 수를 카운트해서 나타내보기.

 

userMemo() => 리액트에서 컴포넌트 성능을 최적화 하는데 사용되는 훅

memo => memoization의 약자 메모리에 넣기
동일한 계산을 반복해야 할 때, 이전의 값을 메모리에 저장함으로써
반복수행을 제거하여 프로그램 실행 속도를 빠르게 해주는 기술

함수형 컴포넌트가 랜더링 => 컴포넌트 함수 호출 => 모든 내부 변수 초기화 

useMemo 랜더링 => 함수 호출 => memoize 된 함수를 재사용 

 

    const countActiveUser = (users) => {
        // user.active 가 true 인 사용자를 카운트해서 리턴
        return (users.filter(user => user.active).length);
    }

    const count = useMemo(() => countActiveUser(users), [users])

 

 

 

필터를 이용해서 true인 수의 길이를 리턴해서 바로 받아주고     

 

<div>완료 사용자 수 : {count}</div> 를 추가해서 나타내주면 

 

결과

 

누르면 완료 사용자 수가 늘어나는 걸 볼 수 있음.

 


 

css파일 안만들고 hover 해보기

1. useState로 상태정의

 const [isHovered, setIsHovered] = useState(false);
 

2. 원하는 css 작성

위에서 정의했던걸 이용해서 호버됐을때, 안됐을때 ture , false로 backgrounColor를 설정

    const buttonStyle = {
        marginBottom: "40px",
        width: "78%",
        backgroundColor: isHovered ? "blue" : "#007bff", 
    };
 

3. onMouseEnter , onMouseLeave 이벤트를 이용해서 true, false 일때 스타일이 작동하도록 설정

  <Button style={buttonStyle}  onClick={onCreate}
            onMouseEnter={() => setIsHovered(true)}
            onMouseLeave={() => setIsHovered(false)}
            >Create</Button>{' '}
 

 


 

배웠던거 응용해서 TodoList 만들기

조건

1. 인풋 2개로 내용을 받고 추가 / 삭제 버튼 있어야함

2. 리스트 안의 내용을 눌러 취소선을 그을 수 있어야함

3. 그냥 만들기만하지말고 CSS로 나름 꾸미기

 

import React from 'react';
import TodoCreate from './TodoCreate';
import Todo from './Todo';
import { useState } from 'react';
import { useRef } from 'react';
import './Todo.css';


const TodoList = () => {

    const nextId = useRef(0);

    const [todos, setTodos] = useState([]);

    const [todoname , setTodoname] = useState();

    const onChange = (e) => {
        setTodoname(e.target.value);
    }

    const onAdd = () => {
        const todo = {
            id:nextId.current,
            todoname : todoname,
        };

        setTodos( todos.concat(todo));

        setTodoname('');

        nextId.current += 1;
    }

    const onRemove = (id) => {
        setTodos(todos.filter(todo => todo.id !== id))
    }

    const onToggle = (id) => {
        setTodos(todos.map( todo => todo.id === id ? { ...todo, active : !todo.active} : todo))
    }

    return (
        <div className='todolist'>
            <h1 className="todo-title">My Todo List</h1>
            
            
            <TodoCreate todoname={todoname} onChange={onChange} onAdd={onAdd}/>
            

            <ul className='todo-list'>
            {
                todos.map( t => (
                    <li className='todo-item'>
                    <Todo todo = {t} key = {t.id} onRemove = {onRemove} onToggle={onToggle} />
                    </li>
                ))
            }
            </ul>
        </div>
    );
};

export default TodoList;

 

import React from 'react';
import './Todo.css';

const Todo = ( {todo, onRemove, onToggle}) => {
    return (
        <div className='todo'>

        <h3>
            <span
            style={{
                color: todo.active ? "red" : "#ff6f61",
                textDecoration: todo.active ? "line-through" : "none",
                cursor:"pointer"
                }}  
            onClick={() => onToggle(todo.id)}>{todo.todoname}</span>

            <button onClick={() => onRemove(todo.id)}>X</button>
        </h3>

        </div>
    );
};

export default Todo;

 

import React from 'react';
import './Todo.css';


const TodoCreate = ({todoname, onChange, onAdd}) => {
    return (
        <div className='todocreate'>
            <div className='todo-input'>
            <input type="text" name='todoname' placeholder='Todo' onChange={onChange} value={todoname}/>
            <button onClick={onAdd}>add</button>
            </div>
        </div>
    );
};

export default TodoCreate;

 

.todo-input input {
    flex: 1;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 16px;
}

body{
    background-color: #f9f5f0;
}
.todo-input {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}
.todo-input input:focus {
    border-color: #ff9aa2; 
    outline: none;
}

.todocreate{
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #f9f9f9;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    margin-bottom: 40px;
}
.todo-input button:hover {
    background-color: #f5a4a4;
}

.todocreate button{
    padding: 10px 20px;
    background-color: #f6c1c1;
    border: none;
    border-radius: 4px;
    color: #fff;
    font-size: 16px;
    cursor: pointer;
}


.todo-list {
    list-style-type: none;
    padding: 0;
}

.todo-item {
    width: 60%;
    margin: 0 auto;
    padding: 15px;
    margin-bottom: 10px;
    background-color: #fef5f5; 
    border: 1px solid #f1c6c6;
    border-radius: 8px;
    font-size: 18px;
    transition: background-color 0.3s ease, transform 0.2s ease;
    
}

.todo-title {
    color: #b67ccf;
    margin-bottom: 20px;
}
.todo-item:hover {
    background-color: #fce4e4; 
    transform: scale(1.02);
}

.todo-item button {
    padding: 8px 12px;
    background-color: #ff9aa2; 
    border: none;
    border-radius: 4px;
    color: #fff;
    font-size: 14px;
    cursor: pointer;
    transition: background-color 0.3s ease, transform 0.2s ease;
    outline: none;
    display: inline-block;
    text-align: center;
}
.todo-item button:hover {
    background-color: #ff6f6f; 
    transform: scale(1.05);
}

.todo{
    width: 100%;
}
.todo h3{
    display: flex;
    justify-content: space-between;
    
}
.todo h3 span{
    margin-left: 60px;
}

 

결과 

 

 


 

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
useEffect((function),deps)
function : 실행시킬 함수 
deps : 배열형태
[] 빈배열 : 마운트 될 때 만 실행
x : 매번 랜더링 될 때 마다 실행
[name] : 업데이트 될 때 마다 실행


 

https://jsonplaceholder.typicode.com/users 에서 데이터를 가져와보기

 

import React from 'react';
import { useEffect } from 'react';
import { useState } 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{
            // 요청이 시작되면 loding의 상태를 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}) : {user.email}</li>
                ))
            }
            </ul>
            {/* button을 추가하여 클릭시 user 데이터가 뜰 수 있도록 설정 */}
            <button onClick={fetchUsers}>Create</button>
        </div>
    );
};

export default User;

 

버튼을 누르면 데이터를 가져와서 생성하는 것을 볼 수 있음.

'React 수업 정리' 카테고리의 다른 글

Board 만들어보기  (0) 2024.09.19
React 5일차  (0) 2024.09.10
React 3일차  (0) 2024.09.06
React 2일차  (1) 2024.09.05
React 1일차  (2) 2024.09.04