내일배움캠프 4기 React 27일차(2차원배열, React 과제)

최영진·2022년 12월 6일
0

1. 프로그래머스(2차원 배열)

2차원 배열을 나타내기 위해선 반복문을 통해 배열속에 배열을 생성해도 되지만
es6 에서 사용가능한 방법으로 쉽게 생성이 가능하다.

answer = Array.from(Array(new_length), () => new Array(n));

new_length = 배열의 총길이
n = 2차원 배열의 길이

배열의 length 는 8이고 n 은 2 이다.
2 * 4 의 배열로 나타내야한다.

이 문제는 배열속 위치index 를 기준으로 풀었다.

function solution(num_list, n) {
    var  new_length = num_list.length / n;
    var answer = Array.from(Array(new_length), () => new Array(n));
    for (let i=0; i<=num_list.length-1; i++){
        answer[Math.floor(i/n)][i%n] = num_list[i]
    }
    return answer;
}

answer 를 2차원배열로 선언해주었고 배열의 길이는 length/n 으로 정했다.

0번째 인덱스는 0 / 2 의 몫은 0, 나머지도 0
1번째 인덱스 1 / 2 의 몫은 0, 나머지는 1 이다.

여기서 array[][] 에서 첫번쨰 [] 은 몫, 즉 나눈값의 내림 값이고
두번째 [] 의 순서는 나머지의 값으로 배치했다.

2. React 과제 (todolist)

App.js

import React, { useState } from "react";
import Todolist from "./components/Todolist";
import "./App.css";

const App = () => {
  const [todolist, setTodoList] = useState([]);
  const [title, setTitle] = useState("");
  const [list, setList] = useState("");
  const addTodo = () => {
    const newTodo = {
      id: todolist.length + 1,
      title: title,
      list: list,
      isDone: false,
    };
    setTodoList([...todolist, newTodo]);
    setList("");
    setTitle("");
    console.log(todolist);
  };
  const delTodo = (id) => {
    const newTodoList = todolist.filter((todo) => todo.id !== id);
    setTodoList(newTodoList);
  };
  const comClick = (id) => {
    const comTodo = todolist.map((todo) => {
      if (todo.id === id) {
        return {
          ...todo,
          isDone: !todo.isDone,
        };
      } else {
        return { ...todo };
      }
    });
    setTodoList(comTodo);
  };

  return (
    <div className="base">
      <header className="header">나의 Todolist</header>
      <div className="input_box">
        <input
          className="input"
          type="text"
          placeholder="제목을 입력하세요"
          onChange={(e) => setTitle(e.target.value)}
          value={title}
        />
        <input
          className="input"
          type="text"
          placeholder="내용을 입력하세요"
          onChange={(e) => setList(e.target.value)}
          value={list}
        />
        <button className="add_Bt" onClick={addTodo}>
          추가하기
        </button>
      </div>
      <div className="list_box">
        <div className="working_box">
          <p>Working</p>
          {todolist.map((todo) => {
            if (!todo.isDone) {
              return (
                <Todolist
                  todo={todo}
                  key={todo.id}
                  delTodo={delTodo}
                  comClick={comClick}
                />
              );
            } else {
              return null;
            }
          })}
        </div>
        <div className="done_box">
          <p>Done</p>
          {todolist.map((todo) => {
            if (todo.isDone) {
              return (
                <Todolist
                  todo={todo}
                  key={todo.id}
                  delTodo={delTodo}
                  comClick={comClick}
                />
              );
            } else {
              return null;
            }
          })}
        </div>
      </div>
    </div>
  );
};

export default App;

Todolist.js

function Todolist(props) {
  return (
    <div className="todo_box">
      <div className="todo_title">{props.todo.title}</div>
      <div className="todo_text">{props.todo.list}</div>
      <button className="del_Bt" onClick={() => props.delTodo(props.todo.id)}>
        삭제하기
      </button>
      <button className="com_Bt" onClick={() => props.comClick(props.todo.id)}>
        {props.todo.isDone ? "취소하기" : "완료하기"}
      </button>
    </div>
  );
}

export default Todolist;

todolist , title, text 입력 값들을 useState 를 사용하여 정의하였다.

1. 제목과 내용을 입력하고, [추가하기] 버튼을 클릭하면 Working에 새로운 Todo가 추가되고 제목 input과 내용 input은 다시 빈 값으로 바뀌도록 구성해주세요.

input 에 title 과 list 를 작성하고 추가하기를 클릭하면 onClick 이벤트 발생!
addTodo 에서 객체에 id, title, list, isDone 값을 받으면Todolist 에서 props 로
값을 받아 실행되고 map 메소드를 이용해
setTodoList([]) 빈값에 넣어주어 setTodoList([...todolist, newTodo]) 로 저장.
그 후 입력된 title 과 list input 값은
setTitle, setList('') 로 리셋 해준다.

2. Todo의 isDone 상태가 true이면, 상태 버튼의 라벨을 취소, isDone이 false 이면 라벨을 완료 로 조건부 렌더링 해주세요.

객체에 값을 저장할 때 아직 끝내지 못한 Todo 기 때문에 idDone: false 를 할당.

완료하기 버튼을 클릭하면 .map 을 이용해 클릭한 id값과 같은 todo 를 찾아
isDone: True 로 변경하고 리스트를 재 렌더링한다.

삼항연산자를 이용해
isDone ? "취소하기" : "완료하기" >> true : false
버튼의 문구를 변경한다.

3. Todo의 상태가 Working 이면 위쪽에 위치하고, Done이면 아래쪽에 위치하도록 구현합니다.

Working div 와 Done div 를 따로 두고 if 조건문을 사용하여,
isDone 이 false 라면 Working, true 면 Done 에 위치 시킨다.

4. Layout의 최대 넓이는 1200px, 최소 넓이는 800px로 제한하고, 전체 화면의 가운데로 정렬해주세요.

max-width: 1200px, min-width:800px, width:100% 설정

flex가 잘 안먹혀서
left: -50% , transform:translateX(-50%) 로 중앙 정렬함.

5. 컴포넌트 구조는 자유롭게 구현해보세요.

Todolist.js 는 export, import 가 간단하여 분리 하였다.

하지만 addTodo, delTodo, comTodo 같은 경우엔
function App() 안에 있는 것들이라 어떻게 해야할지 감이 오지 않았다.

profile
안녕하시오.

2개의 댓글

comment-user-thumbnail
2022년 12월 7일

목은 좀 괜찮으신가요? 정리 고생하셨습니다 ㅎㅎ

1개의 답글