SPACE RUMI

Hi, I am rumi. Let's Splattack!

[IT] 프로덕트 개발/React - 리액트

[React] localStorage 사용하여 Todo list 만들기

백루미 2022. 9. 15. 11:17
반응형

 

타입설정과 useState

list들의 타입을 정해주고, map 돌릴 list state와 새로 추가할 newTodo state를 만들어준다.

type Lists = {
  id:number,
  title:string,
  checked:boolean,
}

...
const [list, setList] = useState<Lists[]>([]);
const [newTodo, setNewTodo] = useState({
    id: new Date().getTime(),
    title: "",
    checked: false,
});

 

Mark up

볼만하게 커스터마이징을 해준다.

<section>
    <div className="flex-center">
        <div className="base-input-wrap minmax300">
          <input type="text" name="title" value={newTodo.title} onChange={onChangeInput} className="base-input" placeholder="list name" />
        </div>
        <button className="base-btn ml10" onClick={addList} disabled={!newTodo.title}> 
          추가
        </button>
    </div>
    <ul className="font16 mt20">
      {list.map((item, index) => {
        return (
          <li key={index} className="flex-center-between">
            <div>
                <input type="checkbox" className="mr10" value={item.id} checked={item.checked} onChange={(e) => onCheckboxClick(index)} /> 
                <span className={item.checked ? "text-line text-primary4" :''}>{item.title}</span> 
            </div> 
            <button className="only-text-btn text-red" onClick={() => removeList(index)}>remove</button>
          </li>
        );
      })}
    </ul>
  </section>

 

기능구현

localStorage에 setItem 할때는 문자열로 넣어주고, getItem 할때는 파싱해서 꺼낸다.
새로고침해도 localStorage에 저장된 리스트가 있다면 state에 set해주기 때문에 날아가지 않는다.
id 값을 비교하여 필터링해도 된다.

  const onChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newTodoTemp = { ...newTodo, [e.target.name]: e.target.value };
    setNewTodo(newTodoTemp); // 인풋 value가 바뀔때마다 새로운 todo를 set해준다
  };

  const addList = () => {
    if (newTodo.title) { // 새로 추가될 todo title 값이 있으면 
      const newList = list.concat(newTodo); //기존 list에 new Todo를 추가하고
      setList(newList); // set해준다
      localStorage.setItem('todos', JSON.stringify(newList)); //로컬스토리지에도 set한다.
    }
    setNewTodo({ ...newTodo, title: "" }); // input 초기화
  };

  const removeList = (index: any) => {
    const removedList = list.filter((_, i) => i !== index); //클릭한 요소를 제외한 새 배열을 만들어
    setList(removedList); // list를 교체한다.
    localStorage.setItem('todos', JSON.stringify(removedList));
  };

  const onCheckboxClick = useCallback((index: number) => {
    const newList = list.map((item, i) => i === index ? {...item, checked: !item.checked} : item);
    setList(newList);
    localStorage.setItem('todos', JSON.stringify(newList));
  }, [list]);

  useEffect(()=>{
    const localList = localStorage.getItem('todos');
    if(localList) setList(JSON.parse(localList)); //최초 렌더링 시 로컬스토리지에 저장된 값이 있으면 리스트에 셋한다.
  },[])

 

반응형