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[][] 에서 첫번쨰 [] 은 몫, 즉 나눈값의 내림 값이고
두번째 [] 의 순서는 나머지의 값으로 배치했다.
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 를 사용하여 정의하였다.
input 에 title 과 list 를 작성하고 추가하기를 클릭하면 onClick 이벤트 발생!
addTodo 에서 객체에 id, title, list, isDone 값을 받으면Todolist 에서 props 로
값을 받아 실행되고 map 메소드를 이용해
setTodoList([]) 빈값에 넣어주어 setTodoList([...todolist, newTodo]) 로 저장.
그 후 입력된 title 과 list input 값은
setTitle, setList('') 로 리셋 해준다.
객체에 값을 저장할 때 아직 끝내지 못한 Todo 기 때문에 idDone: false 를 할당.
완료하기 버튼을 클릭하면 .map 을 이용해 클릭한 id값과 같은 todo 를 찾아
isDone: True 로 변경하고 리스트를 재 렌더링한다.
삼항연산자를 이용해
isDone ? "취소하기" : "완료하기" >> true : false
버튼의 문구를 변경한다.
Working div 와 Done div 를 따로 두고 if 조건문을 사용하여,
isDone 이 false 라면 Working, true 면 Done 에 위치 시킨다.
max-width: 1200px, min-width:800px, width:100% 설정
flex가 잘 안먹혀서
left: -50% , transform:translateX(-50%) 로 중앙 정렬함.
Todolist.js 는 export, import 가 간단하여 분리 하였다.
하지만 addTodo, delTodo, comTodo 같은 경우엔
function App() 안에 있는 것들이라 어떻게 해야할지 감이 오지 않았다.
목은 좀 괜찮으신가요? 정리 고생하셨습니다 ㅎㅎ