Front-end/React 실습
리액트 사용편
by warrior.p
2022. 4. 5.
import { formatRelativeDate } from './js/helpers.js';
import store from './js/store.js';
const TabType = {
KEYWORD: 'KEYWORD',
HISTORY: 'HISTORY',
};
const TabLabel = {
[TabType.KEYWORD]: '추천 검색어',
[TabType.HISTORY]: '최근 검색어',
};
class App extends React.Component {
constructor() {
super();
this.state = {
searchKeyword: '',
searchResult: [],
submitted: false,
selectedTab: TabType.KEYWORD,
keywordList: [], //추천검 색어 리스트
historyList: [], //최근 검색어 리스트
};
}
componentDidMount() {
const keywordList = store.getKeywordList(); //store.js에 있는 keyWordList를 가져오는
const historyList = store.getHistoryList();
this.setState({
//상태 업데이트
keywordList,
historyList,
});
}
handleSubmit(event) {
event.preventDefault();
console.log('TODO:handleSubmit', this.state.searchKeyword);
this.search(this.state.searchKeyword);
}
search(searchKeyword) {
const searchResult = store.search(searchKeyword);
const historyList = store.getHistoryList();
this.setState({
searchKeyword,
searchResult,
historyList,
submitted: true,
});
}
handleReset() {
//setState()는 항상 비동기적(여러번 호출 하더라도 최소한의 변경을 위해서)
this.setState({
searchKeyword: '',
submitted: false,
});
}
//검색어 입력을 처리하는 부분
handleChangeInput(event) {
//컴포넌트 상태를 변경하려면 직접 수정하지 말고 컴포넌트class가 제공하는 set메소드를 사용해라!
//컴포넌트의 상태를 변화시키겠다는 컴포넌트와의 직접적인 약속. 잊지말자 setState()
const searchKeyword = event.target.value;
if (searchKeyword.length <= 0 && this.state.submitted) {
return this.handleReset();
}
this.setState({ searchKeyword });
}
handleClickRemoveHistory(event, keyword) {
event.stopPropagation(); //버블링을 막는 함수!
store.removeHistory(keyword);
const historyList = store.getHistoryList();
this.setState({ historyList });
}
render() {
const searchForm = (
<form
onSubmit={event => this.handleSubmit(event)}
onReset={() => this.handleReset()}
>
<input
type='text'
placeholder='검색어를 입력하세요'
autoFocus
value={this.state.searchKeyword}
onChange={event => this.handleChangeInput(event)}
/>
{this.state.searchKeyword.length > 0 && (
<button type='reset' className='btn-reset'></button>
)}
</form>
);
const searchResult =
this.state.searchResult.length > 0 ? (
<ul className='result'>
{this.state.searchResult.map(item => {
return (
<li key={item.id}>
<img src={item.imageUrl} alt={item.name} />
<p>{item.name}</p>
</li>
);
})}
</ul>
) : (
<div className='empty-box'>검색 결과가 없습니다</div>
);
const keywordList = (
<ul className='list'>
{this.state.keywordList.map(({ id, keyword }, index) => (
<li key={id} onClick={() => this.search(keyword)}>
<span className='number'>{index + 1}</span>
<span>{keyword}</span>
</li>
))}
</ul>
);
const historyList = (
<ul className='list'>
{this.state.historyList.map(({ id, keyword, date }) => (
<li key={id} onClick={() => this.search(keyword)}>
<span>{keyword}</span>
<span className='date'>{formatRelativeDate(date)}</span>
<button
className='btn-remove'
onClick={event => this.handleClickRemoveHistory(event, keyword)}
/>
</li>
))}
</ul>
);
const tabs = (
<>
<ul className='tabs'>
{Object.values(TabType).map(TabType => (
<li
className={this.state.selectedTab === TabType ? 'active' : ''}
key={TabType}
onClick={() => this.setState({ selectedTab: TabType })}
>
{TabLabel[TabType]}
</li>
))}
</ul>
{this.state.selectedTab === TabType.KEYWORD && keywordList}
{this.state.selectedTab === TabType.HISTORY && historyList}
</>
);
return (
<>
<header>
<h2 className='container'>검색</h2>
</header>
<div className='container'>
{searchForm}
<div className='content'>
{this.state.submitted ? searchResult : tabs}
</div>
</div>
</>
);
}
}
ReactDOM.render(<App />, document.querySelector('#app'));