반응형

이런모양의 todolist를 만들어줄것이다 +버튼을 누르면 밑에 내용이추가되고 ,

내용옆에있는 x를 누르면 내용이삭제되도록 변경해줄예정.

 

Todolist.js (easy.ver) 완성

import React,{useState} from 'react'

const Todolist = ()=>{
    const[list,setlist] = useState([]);
    const[input,setinput] = useState("");

    // 인풋에 입력할때 값을 바꿔줄 함수
    const onChange = (e)=>{
        setinput(e.target.value)
    }
    // +버튼을 클릭하면 리스트에 추가
    const onAddTodo = ()=>{
        const nextlist=[
            ...list,
            {id:list.length+1,text:input}
        ]
        setlist(nextlist); //새로만든 리스트를 list에 적용
        setinput("")//input비워주기
    }
    // // X를 클릭하면 삭제되게
    const delTodoLists = (id) => {
        const nextlist = list.filter(list=> list.id !== id)
        setlist(nextlist)
    }    
    return(
        <div className='todo'>
            <div className='header'>
                <h2>To do List</h2>
                <div>
                    <input onChange={onChange} value={input} />
                    <button onClick={onAddTodo}>+</button>
                </div>
            </div>
            <div>
                <ul className='todoLists'>
                    {list.map(todo=><li key={todo.id}>{todo.text}
                    <span onClick={()=>{delTodoLists(todo.id)}}>X</span></li>)}
                </ul>
            </div>
        </div>
    )
}

export default Todolist;

 

좀 복잡하긴한데 배웠던 내용들을 활용한거라서 천천히 읽으면 그렇게 어렵지는 않다.

App.js에 import 해주고 렌더링하면 이런화면이 나오게된다 css는 아직... 제일마지막에 해보겠다
코드도 하나씩 천천히 다시 써보겠다.

 

우선은 안에 함수와 상태값들 다빼고 html구조만 먼저 잡아보자

const Todolist = ()=>{
    return(
        <div className='todo'>
            <div className='header'>
                <h2>To do List</h2>
                <div>
                    <input/>
                    <button>+</button>
                </div>
            </div>
            <div>
                <ul className='todoLists'>
                    <li>할일이없어요<span>X</span></li>
                </ul>
            </div>
        </div>
    )
}

이제 저기에서 input에 값을 입력하면 input.value가 바뀌고 +버튼을 클릭하면

아래에있는 <ul> 에 <li>가 추가되어서 내용이 들어가게 해줄것이다

 

input에 입력될때 input.value변경

const Todolist = ()=>{
    const [input,setInput] = useState(""); //인풋태그의 초기값은 공백
    const inputchange = (e)=>{ // e.target 는 해당함수를 실행시키는요소 == input
        setInput(e.target.value) //e.target.value == input.value
    }
    return(
        <div className='todo'>
            <div className='header'>
                <h2>To do List</h2>
                <div>
                    <input value={input} onChange={inputchange}/>
                    <button>+</button>
                </div>
            </div>
            <div>
                <ul className='todoLists'>
                    <li>할일이없어요<span>X</span></li>
                </ul>
            </div>
        </div>
    )
}

 

 

+버튼을 누를때 input의 내용이 list에 추가되게 해주고 ul에 보여주기

list 는 키넘버와 내용을 가진 객체를 배열로 저장 [ {key:1,text:할일1 }, {key:2,text:할일2}] 

    const[list,setlist] = useState([])
    const addlist=()=>{
        const newlist = [...list,{key:list.length+1,text:input}]
        setlist(newlist);
        setInput(""); 
    } 리스트값의 상태를 관리할 변수를 useState로 만들어주고(값이 여러개들어가기때문에 배열로만들어준다)

addlist함수가 실행되면 newlist 라는 변수를 만들게되고. 이 변수에는 기존에 리스트에있던값들과

새로운 객체를 추가 해서 저장한다. 새로운 list가저장된변수를 setlist에 넣어서 list상태를 변환시켜준다.

이제 이렇게 만들어진 list 를 렌더링 해줘야한다. 

                <ul className='todoLists'>
                    <li>할일이없어요<span>X</span></li>
                    {list.map(todo=><li key={todo.id}> {todo.text} <span>X</span> </li>)}
                </ul>

list는 배열이기 때문에 배열메소드인 map을 이용해서 새로 html형식으로 만들어서 리턴시켜준다. li에 key가 있는데 key는 요소를 파악하기 위해서 달아주는 거라고 보면된다 key가없다면 변경이 필요하지않은 요소도 같이 변경이 일어날수도있기때문에 달아주는것이다.

 

현재까지의 전체코드

import React,{useState} from 'react'

const Todolist = ()=>{
    const [input,setInput] = useState(""); //인풋태그의 초기값은 공백
    const[list,setlist] = useState([]);
    
    const inputchange = (e)=>{ // e.target 는 해당함수를 실행시키는요소 == input
        setInput(e.target.value) //e.target.value == input.value
    }

    const addlist=()=>{
        const newlist = [...list,
            {id:list.length+1,text:input}
        ]
        setlist(newlist);
        setInput(""); 
    }
    console.log(list)
    return(
        <div className='todo'>
            <div className='header'>
                <h2>To do List</h2>
                <div>
                    <input value={input} onChange={inputchange}/>
                    <button onClick={addlist}>+</button>
                </div>
            </div>
            <div>
                <ul className='todoLists'>
                    {list.map(todo=><li key={todo.id}> {todo.text} <span>X</span> </li>)}
                </ul>
            </div>
        </div>
    )
}

export default Todolist;

 

이제 추가는 잘되는데 삭제는 할수가없다  todolist니까 하고나면 삭제를 해줘야한다. 

 

삭제기능 

    const dellist = (id)=>{
        const newlist=list.filter(list=> list.id !== id)
        setlist(newlist)
    }

id를 받아서 클릭한리스트의 id와 같으면 filter에서 false 가 나와서 걸러지게되고

그외에 list들은 newlist에 저장된다.

setlist에 바뀐 newlist를 넣어서 state를 변경해준다.

{list.map(todo=><li key={todo.id}> {todo.text} 
<span onClick={()=>dellist(todo.id)}>X</span> </li>)}

 태그안에서 파라미터를 주기위해서 함수를  dellist를 실행시키는 화살표함수를 하나 만들어서 사용했다.

이렇게 사용하면 dellist함수에 todo.id를 파라미터로 보내줄수있다.

 

완성코드

import React,{useState} from 'react'

const Todolist = ()=>{
    const [input,setInput] = useState(""); //인풋태그의 초기값은 공백
    const[list,setlist] = useState([]);
    
    const inputchange = (e)=>{ // e.target 는 해당함수를 실행시키는요소 == input
        setInput(e.target.value) //e.target.value == input.value
    }

    const addlist=()=>{
        const newlist = [...list,
            {id:list.length+1,text:input}
        ]
        setlist(newlist);
        setInput(""); 
    }
    const dellist = (id)=>{
        const newlist=list.filter(list=> list.id !== id)
        setlist(newlist)
    }
    console.log(list)
    return(
        <div className='todo'>
            <div className='header'>
                <h2>To do List</h2>
                <div>
                    <input value={input} onChange={inputchange}/>
                    <button onClick={addlist}>+</button>
                </div>
            </div>
            <div>
                <ul className='todoLists'>
                    {list.map(todo=><li key={todo.id}> {todo.text} 
                    <span onClick={()=>dellist(todo.id)}>X</span> </li>)}
                </ul>
            </div>
        </div>
    )
}

export default Todolist;

여기서 끝나면 좋겠지만... 저번에 말했던것처럼 리액트는 모듈별로 나누고 각각 조립해서사용게 장점이기 때문에 이 컴포넌트를 두개로 나눠야한다....(왜 어째서..ㅠ)

Hard.ver 시작

우선은 입력하는 헤더부분과 입력된값을 보여주는 리스트부분 으로 나눠서 컴포넌트를 만들어준다.

 

Todoheader.js

import React from 'react'

const Todoheader = ()=>{

    return(
        <div className='header'>
            <h2>To do List</h2>
            <div>
                <input />
                <button >+</button>
            </div>
        </div>
    )
}

export default Todoheader

Todolists.js

import React from 'react';

const Todolists = ()=>{
    return(
        <div>
            <ul>
                <li>리액트지옥<span>X</span></li>
            </ul>
        </div>
    )
}

export default Todolists

이렇게 두개의 분리된 컴포넌트를 만들고 

App.js 에서 두개를 렌더 해준다.

App.js

  return (
    <div className="App todo">
      <Todoheader/>
      <Todolists/>
    </div>
  );

아까처럼 결과화면을 볼수있다. 이제 사용할함수들을 만들어주고 적용해주면 된다.

이번에는 App.js에서 상태값과 함수를 만들어 props로 각 컴포넌트에 적용해주겠다.

 

App.js

import './App.css';
import Todoheader from './components/Todoheader';
import Todolists from './components/Todolist';
import { useState } from 'react';

function App() {
  const [todoState,setTodostate] = useState({
    todoLists:[],
    inputText:""
  })
  const Change = (e)=>{
    setTodostate({
      ...todoState, //원래있던 todostate값을 저장
      inputText: e.target.value
    });
  };
  const Addlist=()=>{
    const newtodolist = [
      ...todoState.todoLists,
      {id:todoState.todoLists.length,text:todoState.inputText}
    ]
    setTodostate({
        todoLists:newtodolist,
        inputText:""
    })
  }
  const delTodoLists = (id)=>{
    const newtodolist = todoState.todoLists.filter(list=>list.id !== id);
    setTodostate({
      ...todoState,
      todoLists:newtodolist
    })  
  }
  return (
    <div className="App">
      <Todoheader
      inputText={todoState.inputText} //value로 들어갈값
      Change ={Change}
      Addlist={Addlist}      
      />
      <Todolists
      todoLists = {todoState.todoLists} // li를 만들기위해 리스트값을 받아옴
      deltodolists = {delTodoLists}
      />
    </div>
  );
}

export default App;

좀 쉽게 설명하자면 아까 한파일에서 만들었던걸 이번에는 App.js에서 만든다고 보면된다

조금 다른점은 이번에는 상태값에 input값도 같이 포함되어있다는점.. 그래서 값을 변경해줄때

input값도 잊지말고 같이 설정해주어야한다.

 

나머지는 다 똑같이 쓰던 함수들을 정의하고 Todoheader에 인풋값이 변할때 value값을 바꿔주는 함수와 value 로 들어갈 input 값 버튼을 누를때 list 배열에 input값이 추가되는 함수들을 props로 전송해준다.

 

Todoheader.js

import React from 'react'

const Todoheader = ({inputText,Change,Addlist})=>{

    return(
        <div className='header'>
            <h2>To do List</h2>
            <div>
                <input value={inputText} onChange={Change}/>
                <button onClick={Addlist}>+</button>
            </div>
        </div>
    )
}

export default Todoheader

Todoheader에서는 보내준 props값을 객체 구조분해 할당으로 받아서 필요한 함수와 변수를 넣어준다.

아까 만든부분에서 위에 함수를 정의했던부분과 state값을 만들었던부분만 없어졌다고 보면 편하다.

 

Todolists.js

import React from 'react';

const Todolists = ({todoLists,deltodolists})=>{
    return(
        <div>
            <ul>
                {todoLists.map(list=><li key={list.id}>{list.text}
                <span onClick={()=>deltodolists(list.id)}>X</span></li>)}
            </ul>
        </div>
    )
}

export default Todolists

Todolists에서는 App.js에서 props로 보내준 list값과 deltodolist함수를 이용해서

전처럼 <li>를 만들어서 뿌려주고 

그 안에 deltodolists함수를 넣어줬다. 

기능적으로 똑같이 추가와 삭제가가능하다.

 

 

이제 여기에 css를 넣으면 완성!

 

Todo.css

* { margin: 0; padding: 0; box-sizing: border-box; vertical-align: middle;}
li{
    list-style: none;
    border-bottom: 1px solid #ccc;
}
span{
    float: right;
}
.todo {
    width: 80%;
    max-width: 800px;
    margin: 0 auto;
}
.header {
    background-image: linear-gradient(to right, #9795f0 0%, #fbc8d4 100%);
    height: 140px;
    padding-top: 30px;
}
.header h2 {
    color: #fff;
    font-size: 32px;
}
.header input {
    width: 70%;
    height: 40px;
    border-radius: 20px;
    border: none;
    outline: none;
    padding-left: 30px;
}
.header button {
    height: 40px;
    width: 40px;
    border-radius: 20px;
    border: none;
    outline: none;
    background: #fff;
    color: #fbc8d4;
    font-size: 24px;
    font-weight: bold;
    margin-left: 8px;
}
.todoLists {
    list-style: none;
}
.todoLists li {
    line-height: 40px;
    background-color: #f5f5f5;
    text-align: left;
    padding: 0 20px;
    border-bottom: 1px solid #ccc;
}
.todoLists li button {
    float: right;
    border: none;
    outline: none;
    line-height: 40px;
}

 

이번주까지 배운React 내용들은 주말동안 전부 정리한것같다 확실히 블로그에 이렇게 한줄씩 쓰면서

남한테 설명하는느낌으로 정리를 하다보니 이해도가 좀 더 잘 올라가는것같다. 다음주 리액트도 열심히 정리하자,

네이버 블로그에 써놓은 내용도 조금씩 옮기고,, ㅠ

반응형

+ Recent posts