728x90
App.js
import { Component } from "react";
import Form from "./components/Form";
import TodoItemList from "./components/TodoItemList";
import TodoListTemplate from "./components/TodoListTemplate";
class App extends Component {
id = 4;
// 초기 데이터 정보
state = {
input: '',
todos: [
{ id: 0, text: '할일1', checked: false },
{ id: 1, text: '할일2', checked: true },
{ id: 2, text: '할일3', checked: false },
{ id: 3, text: '할일4', checked: true }
]
}
state 초기 데이터 생성
render
render() {
return (
<div>
<TodoListTemplate
form={
<Form value={this.state.input}
onKeyPress={this.handleKeyPress}
onChange={this.handleChange}
onCreate={this.handleCreate}
/>
}>
<TodoItemList
todos={this.state.todos}
onRemove={this.handelRemove}
onToggle={this.handelToggle} />
</TodoListTemplate>
</div >
)
}
}
export default App;
Form.js
import './Form.css'
const Form = ({ value, onKeyPress, onChange, onCreate }) => {
return (
<div className="form">
<input value={value}
onChange={onChange}
onKeyPress={onKeyPress} />
<div className='create-button' onClick={onCreate}>추가</div>
</div>
)
}
export default Form;
const Form = ({ value, onKeyPress, onChange, onCreate }) => {
TodoListTemplate.js
import './TodoListTemplate.css'
const TodoListTemplate = ({ form, children }) => {
return (
<main className='todo-list-template'>
<div className='title'>오늘 할 일</div>
<section className="form-wrapper">{form} </section>
<section className="todos-wrapper">{children} </section>
</main>
)
}
export default TodoListTemplate;
TodoItemList.js
import { Component } from "react";
import TodoItem from "./TodoItem";
class TodoItemList extends Component {
render() {
const { todos, onRemove, onToggle } = this.props
const todoList = todos.map(({ id, text, checked }) => (
<TodoItem
key={id}
id={id}
text={text}
checked={checked}
onRemove={onRemove}
onToggle={onToggle} />
))
return (
<div>
{todoList}
</div>
)
}
}
export default TodoItemList;
App.js 에서 컴포넌트 호출
<TodoItemList
todos={this.state.todos}
onRemove={this.handelRemove}
onToggle={this.handelToggle} />
TodoItemList.js 에서 this.props 으로 값을 각각 받는다.
const { todos, onRemove, onToggle } = this.props
TodoItem 으로 map (반복문을 통해) 각각 생성
const todoList = todos.map(({ id, text, checked }) => (
<TodoItem
key={id}
id={id}
text={text}
checked={checked}
onRemove={onRemove}
onToggle={onToggle} />
))
TodoItem.js
import { Component } from "react";
import './TodoItem.css';
class TodoItem extends Component {
render() {
const { text, checked, id, onRemove, onToggle } = this.props
return (
<div className="todo-item"
onClick={() => onToggle(id)}>
<div className="remove"
onClick={e => {
e.stopPropagation();
onRemove(id)
}
}>
×
</div >
<div className="{`todo-text ${checked && 'checked'}`}">
<div> {text}</div>
</div>
{checked && <div className="check-mark">✓</div>}
</div >
)
}
}
export default TodoItem;
const { text, checked, id, onRemove, onToggle } = this.props
<TodoItem
key={id}
id={id}
text={text}
checked={checked}
onRemove={onRemove}
onToggle={onToggle} />
TodoItem 을 호출할 때의 변수 순서와는 관계 없이 받을 수 있나보다
아이템 선택시 onClick 바로 실행-> 토글 onToggle(id) 호출, id를 넘겨준다.
<div className="todo-item"
onClick={() => onToggle(id)}>
아이템 삭제표시
<div className="remove"
onClick={e => {
e.stopPropagation(); // 이벤트 전파 방지
onRemove(id)
}
}>
× // ⊗
</div >
아이템 체크 표시
<div className="{`todo-text ${checked && 'checked'}`}">
<div> {text}</div>
</div>
{checked && <div className="check-mark">✓</div>}
`` 백틱 : 문자와 문자열 연결시 활용
폼 태그 데이터 입력
// 폼 태그에 글쓰기 가능 , state내 input에 값이 들어간다. -> value={this.state.input}
handleChange = e => {
this.setState({
input: e.target.value
})
}
onChange={this.handleChange}
input : ... // -> input = ...
//토클
handelToggle = (id) => {
const { todos } = this.state // todos
const index = todos.findIndex(todo => todo.id === id) //1
const selected = todos[index] // { id: 1, text: '치킨먹기2', checked: true }
const nextTodos = [...todos] // { id: 1, text: '할일2', checked: true },
nextTodos[index] = {
...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
checked: !selected.checked // 변경될 데이터만 새로 입력
}
// state 상태 변경은 setSate 필수
this.setState({
todos: nextTodos
})
}
nextTodos[index] = {
...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
checked: !selected.checked // 변경될 데이터만 새로 입력
}
할일 추가
//입력하고 엔터키
handleKeyPress = e => {
if (e.key == 'Enter') { //입력된 키값 검사
this.handleCreate()
}
}
//추가
handleCreate = () => {
const { input, todos } = this.state
this.setState({
input: '',
todos: todos.concat({ //concat 으로 값 추가
id: this.id++, // 아이디 +1 추가
text: input, // input: e.target.value : 입력된 값이 들어간다.
checked: false
})
})
}
할일 삭제
//삭제
handelRemove = id => {
console.log("id : " + id)
const { todos } = this.state
const nextTodos = todos.filter(todo => todo.id !== id)
this.setState({
todos: nextTodos
})
}
전체 코드
더보기
import { Component } from "react";
import Form from "./components/Form";
import TodoItemList from "./components/TodoItemList";
import TodoListTemplate from "./components/TodoListTemplate";
class App extends Component {
id = 4;
// 초기 데이터 정보
state = {
input: '',
todos: [
{ id: 0, text: '할일1', checked: false },
{ id: 1, text: '할일2', checked: true },
{ id: 2, text: '할일3', checked: false },
{ id: 3, text: '할일4', checked: true }
]
}
// 폼 태그에 글쓰기 가능 , state내 input에 값이 들어간다. -> value={this.state.input}
handleChange = e => {
this.setState({
input: e.target.value
})
}
//토클
handelToggle = (id) => {
const { todos } = this.state // todos
const index = todos.findIndex(todo => todo.id === id) //1
const selected = todos[index] // { id: 1, text: '치킨먹기2', checked: true }
const nextTodos = [...todos] // { id: 1, text: '할일2', checked: true },
nextTodos[index] = {
...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
checked: !selected.checked // 변경될 데이터만 새로 입력
}
// state 상태 변경은 setSate 필수
this.setState({
todos: nextTodos
})
}
//입력하고 엔터키
handleKeyPress = e => {
if (e.key == 'Enter') { //입력된 키값 검사
this.handleCreate()
}
}
//추가
handleCreate = () => {
const { input, todos } = this.state
this.setState({
input: '',
todos: todos.concat({ //concat 으로 값 추가
id: this.id++, // 아이디 +1 추가
text: input, // input: e.target.value : 입력된 값이 들어간다.
checked: false
})
})
}
//삭제
handelRemove = id => {
console.log("id : " + id)
const { todos } = this.state
const nextTodos = todos.filter(todo => todo.id !== id)
this.setState({
todos: nextTodos
})
}
render() {
return (
<div>
<TodoListTemplate
form={
<Form value={this.state.input}
onKeyPress={this.handleKeyPress}
onChange={this.handleChange}
onCreate={this.handleCreate}
/>
}>
<TodoItemList
todos={this.state.todos}
onRemove={this.handelRemove}
onToggle={this.handelToggle} />
</TodoListTemplate>
</div >
)
}
}
export default App;
props
여러 매개변수 대표로 받음
import './ExpenseItem.css';
function ExpenseItem(props){
return (
<div className='expense-item'>
<div>2022 12 03</div>
<div className='expense-item__description'>
<h2>{props.title}</h2>
<div className='expense-item__price'>{props.amount}</div>
</div>
</div>
)
}
export default ExpenseItem;
import ExpenseItem from "./components/ExpenseItem";
function App() {
const expenses = [
{
id: 'e1',
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
},
{ id: 'e2', title: 'New TV', amount: 799.49, date: new Date(2021, 2, 12) },
{
id: 'e3',
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
},
{
id: 'e4',
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
},
];
return (
<div>
<h2>started</h2>
<ExpenseItem
title={expenses[0].title}
amount={expenses[0].amount}
/>
</div>
);
}
export default App;
'Front-end > React\RN' 카테고리의 다른 글
리액트 state 상태 저장, 업데이트 (0) | 2022.12.08 |
---|---|
리액트 배열 반복 map() 함수 활용, filter (0) | 2022.12.08 |
리액트 Fetch API 와 axios 를 통해 서버와 통신하기 (0) | 2022.06.16 |
리액트 Movie API를 활용한 영화 목록 사이트 (2) | 2022.06.07 |
리액트 프로젝트 생성 시작 (0) | 2022.06.04 |
댓글