React - practice(Simple To Do List)(2)

두두두·2022년 10월 16일
0

React

목록 보기
8/21

삭제 기능 추가

삭제 기능을 추하하기 위해 li안에 버튼 생성

<li key={index}><span>{item}</span> <button>X</button></li>

버튼을 클릭했을 때 해당 todo가 삭제되는 함수를 onDelete로 생성한다
요소를 구분하는 key값은 index와 같으므로 onDelete 함수의 인자로 index값을 넘긴다

<li key={index}><span>{item}</span>
  	<button onClick={() => onDelete(index)}>X</button></li>

이 때 onClick={() => onDelete(index)}onClick={onDelete(index)}로 작성하면 클릭될 때가 아닌 rendering될 때 실행되므로 주의

onDelete함수는 index를 받아 같은 위치인 요소(cur)을 제외한 배열을 todos로 수정한다.
filter함수는 조건에 맞는 요소들로 새로운 배열을 반환하는 함수로
(현재 요소, 인덱스값, 호출한 배열)을 인자로 갖는다

  const onDelete = (index) => {
      setTodos((curArray) => 
        curArray.filter((_, curi) => curi!==index));
   }

실행해보면 잘 삭제되는 것을 확인 할 수 있다.

2, 3 삭제

수정 기능 추가

수정 기능을 추가하기 위해 삭제와 같이 버튼을 생성한다

<li key={index}>
  <span>{item}</span> 
  <button>수정</button>
  <button>X</button>
</li>

수정버튼 추가

수정버튼을 클릭하면 해당 span 대신 input박스로 변하고 value에는 해당 내용이 셋팅되게 할 것이다.

그러기 위해서는 li의 모드가 수정 모드인지 아닌지를 저장할 배열변수가 필요하다. 이를 modifyMode라 설정한다. todo가 추가될 때 해당 todo의 모드를 저장할 modifyMode도 false(수정하지 않는다는 의미)값을 하나씩 추가한다

	const [modifyMode, setModifyMode] = useState([]);
    const onSubmit = (event) => {
      ....
      setModifyMode((curArray) => [false, ...curArray]);
    }

수정 버튼을 클릭하면 setModifyMode를 이용하여 같은 index의 modifyMode값만 토글되도록 함수를 작성하였다. 새로운 배열을 반환해야하기 때문에 map을 이용하였다

  const onModifyMode = (index) => {
    setModifyMode((curArray) => 
      curArray.map((cur, curi) => {
        if(curi === index)
          return !cur;
        return cur;
      })
    )
  };

html은 modifyMode[index] 값이 false면 span을 true면 value값이 text인 input을 반환하도록 하였다. onChange 이벤트 없이 value를 설정하면 오류가 발생하므로 text를 수정하여 저장할 onModify함수도 생성하였다. input의 값을 가져와하기 때문에 event를 onModify에 넘겨주었다

	{modifyMode[index] ? 
        <input value={item} 
    	  onChange={(event) => onModify(event, index)}>
        </input> 
        : <span>{item}</span>
	}

onModify 함수는 index값으로 todos에서 수정할 위치를 찾고 input에 적힌 값으로 수정되어야 하기 때문에 다음과 같이 작성하고 실행 시켜보면 잘 작동하는 것을 확인 할 수 있다.

  const onModify = (event, index) => {
    setTodos((curArray) => 
      curArray.map((cur, curi) => {
        if(curi === index)
          return event.target.value;
        return cur;
      })
    )
  };


전체코드

import {useState} from "react";

function App() {
  const [todo, setTodo] = useState("");
  const [todos, setTodos] = useState([]);
  const [modifyMode, setModifyMode] = useState([]);

  const onChange = (event) => setTodo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if(todo === ""){
      return ;
    }
    setTodos((curArray) => [todo, ...curArray]);
    setModifyMode((curArray) => [false, ...curArray]);
    setTodo("");
  };
  const onDelete = (index) => {
    setTodos((curArray) => 
      curArray.filter((_, curi) => curi!==index));
  };
  const onModifyMode = (index) => {
    setModifyMode((curArray) => 
      curArray.map((cur, curi) => {
        if(curi === index)
          return !cur;
        return cur;
      })
    )
  };
  const onModify = (event, index) => {
    setTodos((curArray) => 
      curArray.map((cur, curi) => {
        if(curi === index)
          return event.target.value;
        return cur;
      })
    )
  };

  return (
    <div>
      <h1>My To Dos ({todos.length})</h1>
      <form onSubmit={onSubmit}>
        <input 
          onChange={onChange} 
          value={todo} 
          type="text" 
          placeholder="Write your to do..." 
        />
        <button>Add To Do</button>
      </form>
      <hr />
      <ul>
        {todos.map((item, index) => (
            <li key={index}>
              {modifyMode[index] ? <input value={item} onChange={(event) => onModify(event, index)}></input> : <span>{item}</span>}
              <button onClick={() => onModifyMode(index)}>수정</button>
              <button onClick={() => onDelete(index)}>&times;</button></li>
          ))}
      </ul>
    </div>
  );
}

export default App;

0개의 댓글