第七章.Class Component Project
51097 ワード
📌 ジェネリック構成部品フィーチャー
注意:第六章。クラス構成部品と機能構成部品(+Hook)
🐱 Github
habit-tracker project
📍 プロジェクトの概要(習慣トレーサ)
慣習管理項目
欲しい習慣の回数を増やしたり減らしたりすることができます.
📝 実習コード
app.jsx
habits
<Navbar/>
<Habits/>
import React, { Component, Fragment } from 'react';
import './app.css';
import Habits from './components/habits';
import Navbar from './components/navbar';
//
class App extends Component {
//'습관들(habits)'을 state로 설정
state = {
habits: [
{ id: 1, name: 'Reading', count: 0 },
{ id: 2, name: 'Running', count: 0 },
{ id: 3, name: 'Coding', count: 0 }
]
}
/**
state의 count를 1씩 증가시키는 함수 (map함수 이용)
map() : 현재 state의 habits을 순차적으로 돌며
하위 컴포넌트에서 받은 '습관(habit)'의 id값과
현재 state로 설정된 '습관들(habits)'의 id값을 비교하여
id 값이 같은 경우에(== ' + ' 버튼를 눌렀을 때 전달받은 habit)
state의 해당 habit의 count값을 1 더해준다.
(아래 코드의 item은 'habits'의 'habit'을 의미 / item이란 변수명은 코더의 마음대로 설정)
*/
handleIncrement = (habit) => {
const copyHabits = this.state.habits.map(item => {
if (item.id === habit.id) {
return { ...habit, count: habit.count + 1 }
}
return item;
})
this.setState({
habits: copyHabits
})
}
/**
state의 count를 1씩 감소시키는 함수 (map함수 이용)
위의 handleIncrement와 동일한 개념으로 동작하고,
추가로 마이너스가 연산되었을 때 0미만으로 떨어지는 경우
state를 0으로 설정해준다.
*/
handleDecrement = (habit) => {
const copyHabits = this.state.habits.map(item => {
if (item.id === habit.id) {
const count = habit.count - 1;
return { ...habit, count: count < 0 ? 0 : count };
}
return item;
})
this.setState({
habits: copyHabits
})
}
/**
habit을 삭제하는 함수 (filter함수 이용)
filter() : 현재 state의 habits을 순차적으로 돌며
선택된 habit인 경우를 제외하고 남은 habits를 leftHabits에 담고 이를 현재 state값에 적용한다.
(== 선택된 habit만 제거한다.)
(아래 코드의 item은 'habits'의 'habit'을 의미 / item이란 변수명은 코더의 마음대로 설정)
*/
handleDelete = (habit) => {
const leftHabits = this.state.habits.filter(item => item.id !== habit.id);
this.setState({
habits: leftHabits
})
}
/**
habit을 추가하는 함수
현재의 state값을 복사하고(Spread Operator)
추가로 param으로 받은 name을 habit의 name으로 설정하고 추가해준다.
id값은 중복을 피해주기 위해 Date.now()함수를 이용하였다.
*/
handleAdd = (name) => {
const habitsCopy = [...this.state.habits,
{ id: Date.now(), name: name, count: 0 }
]
this.setState({ habits: habitsCopy });
}
/**
habits속 모든 habit의 count를 0으로 설정해주는 함수
*/
handleReset = () => {
const habits = this.state.habits.map((habit) => {
if (habit.count > 0) {
return { ...habit, count: 0 };
}
return habit;
});
this.setState({
habits
})
}
render() {
return (
<Fragment>
<Navbar totalCount={
this.state.habits.filter(item => item.count > 0).length
}
/>
<Habits
habits={this.state.habits}
onIncrement={this.handleIncrement}
onDecrement={this.handleDecrement}
onDelete={this.handleDelete}
onAdd={this.handleAdd}
onReset={this.handleReset}
/>
</Fragment>
)
}
}
//
export default App;
navbar.jsx
totalCount
import React, { PureComponent } from 'react';
//
class Navbar extends PureComponent {
render() {
return (
<div className="navbar">
<i className="navbar-logo fas fa-leaf"></i>
<span>Habit Tracker</span>
<span className="navbar-count">{this.props.totalCount}</span>
</div>
);
}
}
//
export default Navbar;
habits.jsx
habits
onIncrement / onDecrement / onDelete/ onAdd / onReset
<HabitAddForm/>
<Habit/>
import React, { Component } from 'react';
import Habit from './habit';
import HabitAddForm from './habitAddForm';
import HabitFilter from './habitFilter';
//
class Habits extends Component {
handleIncrement = (habit) => {
this.props.onIncrement(habit);
}
handleDecrement = (habit) => {
this.props.onDecrement(habit);
}
handleDelete = (habit) => {
this.props.onDelete(habit);
}
handleAdd = (name) => {
this.props.onAdd(name);
}
handleFilter = (name) => {
this.props.onFilter(name);
}
render() {
return (
<>
<HabitAddForm onAdd={this.handleAdd} />
<HabitFilter onFilter={this.handleFilter} />
<ul>
{
this.props.habits.map((habit, index) => {
return (
<Habit
key={habit.id}
habit={habit}
onIncrement={this.handleIncrement}
onDecrement={this.handleDecrement}
onDelete={this.handleDelete}
/>
)
})
}
</ul>
<button className="habits-reset"
onClick={this.props.onReset}>
Reset All
</button>
</>
);
}
}
//
export default Habits
habitAddForm.jsx
onAdd
import React, { memo } from 'react';
//
const HabitAddForm = memo(props => {
const formRef = React.createRef();
const inputRef = React.createRef();
const onSubmit = (e) => {
e.preventDefault();
const name = inputRef.current.value;
name && props.onAdd(name);
//inputRef.current.value = '';
formRef.current.reset();
}
//
return (
<form ref={formRef} className="add-from" onSubmit={onSubmit}>
<input
ref={inputRef}
type="text"
className="add-input"
placeholder="Habit" />
<button className="add-button">Add</button>
</form>
);
});
//
export default HabitAddForm;
habit.jsx
habit
onIncrement / onDecrement / onDelete
import React, { memo } from 'react';
//
const Habit = memo((props) => {
//컴포넌트가 UI상 등록이 되었을 때 : 사용자에게 보여질 때
const componentDidMount = () => {
console.log(`habit : ${props.habit.name} mounted`);
}
//컴포넌트 지우기 전에 호출
const componentWillUnmount = () => {
console.log(`habit : ${props.habit.name} will unmount`);
}
//컴포넌트리시브받을때
const componentWillReceiveProps = () => {
console.log("컴포 리시브 받을 때");
}
//props 값을 못 받았을 경우에 대비해 defaultProps설정
const defaultProps = {
id: 0,
name: 'defaultProps',
count: 0
}
const handleIncrement = () => {
props.onIncrement(props.habit);
}
const handleDecrement = () => {
props.onDecrement(props.habit);
}
const handleDelete = () => {
props.onDelete(props.habit);
}
const { name, count } = props.habit;
//
return (
<li className="habit">
<span className="habiit-name">{name}</span>
<span className="habit-count">{count}</span>
<button className="habit-button habit-increase"
onClick={handleIncrement}
<i className="fas fa-plus-square"></i>
</button>
<button className="habit-button habit-decrease"
onClick={handleDecrement}
<i className="fas fa-minus-square"></i>
</button>
<button className="habit-button habit-delete"
onClick={handleDelete}
<i className="fas fa-trash"></i>
</button>
</li>
)
})
//
export default Habit;
Reference
この問題について(第七章.Class Component Project), 我々は、より多くの情報をここで見つけました https://velog.io/@once_developer/6장.-Class형-컴포넌트-Projectテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol