안 쓰던 블로그

To Do List 웹 프로젝트-Todo 글자색 하이라이트 추가하기1 본문

Web/React

To Do List 웹 프로젝트-Todo 글자색 하이라이트 추가하기1

proqk 2020. 7. 24. 00:40
반응형

할 일마다 글자색을 지정할 수 있는 기능을 추가하겠습니다

참고로 여기:https://velopert.com/3480 맨 마지막에 '숙제'부분을 보고 숙제 한 글입니다

 

1. Palette 컴포넌트 생성

 

2. TodoListTemplate에서 Palette가 들어갈 자리를 만든다

scss

.todo-list-template{
    margin-top: 5rem;
    margin-left: auto;
    margin-right: auto;
    width: 500px;
    background: white;
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
    //padding-top: 2rem;
}

.palette-template{
    display: flex;
    justify-content: center;
    background: #f1f3f5;
    display: block;
    padding: 2rem;
}

.title{
    padding: 2rem;
    font-size: 3rem;
    text-align: center;
    font-weight: 100;
    background: #ffa94d;
    color: white;
}
.form-wrapper{
    margin: 0;
    padding: 0;
    font-family: sans-serif;
    border-bottom: #ffa94d;
}

.todos-wrapper{
    margin-top: 2rem;
}

 

js

import React from 'react';
import './PageTemplate.scss';

const PageTemplate = ({form, palette, children}) => {
    return(
        <main className="todo-list-template">
            <div className="title">
                 오늘 할 일
            </div>
            <section className="palette-template">
                {palette}
            </section>
            <section className="form-wrapper">
                {form}
            </section>
            <section className="todos-wrapper">
                {children}
            </section>
        </main>
    );
};

export default PageTemplate;

 

팔레트 색깔이 들어갈 회색 부분 섹션을 나눠주고 Palette를 불러오게 했습니다

 

3. UI추가

-App의 state에 color값 추가

-color를 변경하는 메소드 추가

-색상값을 Palettle 컴포넌트의 props로 전달

-Palette.js를 수정하여 색깔 박스를 클릭하면 반응하게 만든다

 

색상값은 ['#343a40', '#f03e3e', '#12b886', '#228ae6'] 이렇게 쓰겠습니다

 

먼저 Palette.js에서 props를 선언합니다

import React from 'react';
import './Palette.scss';

const Color=({color, active, onClick})=>{
    return(
    );
};

const Palette = ({colors, selected, onSelect})=>{
    return (
    );
};

export default Palette;

이렇게 한 컴포넌트에서 두 개의 컴포넌트를 선언하는 식으로 해볼게요

 

App.js에서 색상값을 선언하고 state에 color값을 추가합니다

const colors = ['#343a40', '#f03e3e', '#12b886', '#228ae6'];

class App extends Component {
    id=3 //예시로 0,1,2를 넣었기 때문에 3

    state={
        input: '',
        todos: [
            { id: 0, text: '리액트 공부', checked: false},
            { id: 1, text: '리액트 에러 고치기', checked: false},
            { id: 2, text: '안녕', checked: true }
        ],
        color: '#343a40'
    }

 

todos 하나가 만들어질 때 color도 같이 지정될 것이니 Create에도 color를 추가합니다

    handleCreate=()=>{
        const{input, todos, color}=this.state;
        this.setState({
            input: '', //인풋을 비운다
            todos: todos.concat({ //concat으로 배열에 추가한다
                id: this.id++,
                text: input,
                checked: false,
                color
            })
        });
    }

 

color를 변경하는 메서드를 만듭니다

    handlePalette=(color)=>{
        this.setState({
            color
        })
    }

 

렌더에 넣어줍니다

    render() {
        const {input, todos, color}=this.state;
        const{
            handleChange,
            handleCreate,
            handleKeyPress,
            handleRemove,
            handleToggle,
            handlePalette
        }=this;

        return (
            <PageTemplate form={<TodoInput
                onChange={handleChange}
                value={input}
                onKeyPress={handleKeyPress}
                onCreate={handleCreate}
                color={color}
            />}
            palette={
                <Palette colors={colors} selected={color} onSelect={handlePalette}/>
            }>
            
            <TodoItemList 
                todos={todos} 
                onToggle={handleToggle}
                onRemove={handleRemove}
            />
            </PageTemplate>
        );
    }

 

PageTemplate에 color를 추가하고 from 아래 palette를 넣었습니다

(코드가 길어서 복잡해보이지만 PageTemplate에 form과 palette TodoItemList가 있는 것입니다)

 

palette는 색깔을 지정하는 네모 박스 div에 달려서 색깔을 지정하는 네모 박스를 구현합니다

실제 코드에서는 <div class="color active/false" style="background: rgb(값,값,값);"></div> 이렇게 됩니다

 

form 부분은 실제 코드에서 <div class="form> <input value style="color: rgb(값,값,값);">이런 식으로 input에 color값이 달리게 될 거고, 색깔 지정 후에 항목을 추가하면 해당 색깔이 적용되어 보입니다

 

여기까지 App.js 전체 코드입니다

import React, { Component } from 'react';
import PageTemplate from './PageTemplate';
import TodoInput from './TodoInput';
import TodoItemList from './TodoItemList';
import Palette from './Palette';

const colors = ['#343a40', '#f03e3e', '#12b886', '#228ae6'];

class App extends Component {
    id=3 //예시로 0,1,2를 넣었기 때문에 3

    state={
        input: '',
        todos: [
            { id: 0, text: '리액트 공부', checked: false},
            { id: 1, text: '리액트 에러 고치기', checked: false},
            { id: 2, text: '안녕', checked: true }
        ],
//        color: '#343a40'
        color: '#12b886'
    }

    handleChange=(e)=>{
        this.setState({input: e.target.value});
    }

    handleCreate=()=>{
        const{input, todos, color}=this.state;
        this.setState({
            input: '', //인풋을 비운다
            todos: todos.concat({ //concat으로 배열에 추가한다
                id: this.id++,
                text: input,
                checked: false,
                color
            })
        });
    }

    handleKeyPress=(e)=>{ //엔터 눌러도 handleCreate 호출
        if(e.key === 'Enter'){
            this.handleCreate();
        }
    }

    handleToggle=(id)=>{
        const {todos}=this.state;
        const index = todos.findIndex(todo => todo.id === id);

        const nextTodos = { 
            ...todos[index], 
            checked: !todos[index].checked
        };

        this.setState({ //slice로 index 전후 데이터를 복사
            todos: [
                ...todos.slice(0,index),
                nextTodos,
                ...todos.slice(index+1, todos.length)
            ]
        });
    }

    handleRemove=(id)=>{
        const {todos}=this.state;
        const index = todos.findIndex(todo=>todo.id===id);

        this.setState({
            todos: [
                ...todos.slice(0, index),
                ...todos.slice(index+1, todos.length)
            ]
        });
    }

    handlePalette=(color)=>{
        this.setState({
            color
        })
    }
    
    render() {
        const {input, todos, color}=this.state;
        const{
            handleChange,
            handleCreate,
            handleKeyPress,
            handleRemove,
            handleToggle,
            handlePalette
        }=this;

        return (
            <PageTemplate form={<TodoInput
                onChange={handleChange}
                value={input}
                onKeyPress={handleKeyPress}
                onCreate={handleCreate}
                color={color}
            />}
            palette={<Palette colors={colors} selected={color} onSelect={handlePalette}/>}>
            
            <TodoItemList todos={todos} onToggle={handleToggle} onRemove={handleRemove}/>
            </PageTemplate>
        );
    }
}

export default App;

 

이제 palette.js의 Palette컴포넌트로 colors, selected, soSelect 3가지 props를 넘겼으니 받는 코드를 씁니다

Palette.js에서 Palette컴포넌트에서 저 값을 받아서 4가지 color 각각의 박스를 만들 건데, 각 박스는 color컴포넌트가 담당합니다

즉, Palette컴포넌트에서 map으로 color컴포넌트 4개로 이루어진 컴포넌트 배열을 만든다는 의미입니다

각 컴포넌트는 4가지 색상 각각의 값을 채운 color컴포넌트가 되겠습니다

 

const Palette = ({colors, selected, onSelect})=>{
    const colorList=colors.map(
        (color)=>(<Color color={color} active={selected===color} onClick={()=>onSelect(color)} key={color}/>)
    );
    return (
        <div className="palette">
            {colorList}
        </div>
    );
};

컴포넌트 배열 colorList를 선언합니다

각 컴포넌트는 color컴포넌트로 이루어져 있고, color는 총 4가지 값이었으니까 4개의 color컴포넌트가 생성됩니다

color컴포넌트의 props를 채우기 위해서 App.js에서 넘겨받은 값을 다시 color컴포넌트로 보내고 있습니다

const Color=({color, active, onClick})=>{
    return(
        <div className={`color ${active && 'active'}`} style={{background: color}} onClick={onClick}>
        </div>
    )
}

color컴포넌트는 이렇습니다

className은 color인데 active면 "color active"라고 되고, 아니면 "color false"가 됩니다

style은 color값을 채워주고 onClick 이벤트를 넣습니다

 

이제 Palette.scss를 만들어서 스타일링 해 줍니다

.palette {
    display: flex;
    justify-content: center;
}

.color{
    width: 2rem;
    height: 2rem;
    opacity: 0.5;
    transition: all 0.2s;
    cursor: pointer;

    &:hover{
        opacity: 0.75;
    }

    &:active, &.active{
        opacity: 1;
    }

    &+&{
        margin-left: 1rem;
    }
    
}

.palette는 중앙 정렬하겠다는 의미

.color는 2rem*2rem 박스를 만들고 처음엔 불투명도 0.5였다가 마우스를 올리면 0.75, 클릭하면 1이 됩니다

&+&는 .color+.color라는 의미로 박스와 박스 사이의 간격을 1rem로 띄워준다는 것입니다

 

Palette.js 전체 코드

import React from 'react';
import './Palette.scss';

const Color=({color, active, onClick})=>{
    return(
        <div className={`color ${active && 'active'}`} style={{background: color}} onClick={onClick}>
        </div>
    )
}

const Palette = ({colors, selected, onSelect})=>{
    const colorList=colors.map(
        (color)=>(<Color color={color} active={selected===color} onClick={()=>onSelect(color)} key={color}/>)
    );
    return (
        <div className="palette">
            {colorList}
        </div>
    );
};

export default Palette;

 

 

이제 색깔 박스가 나왔고, 누르면 불투명도가 바뀝니다

하지만 아직은 아이템의 색깔이 바뀌지는 않습니다

나머지는 다음 글에서 이어집니다

 

반응형
Comments