잎에서 구현한 정적인 화면 구현이 기존 페이지 방식의 퍼블리싱에 해당하며, state 없이 구성을 하였고, 컴포넌트 별로 CSS를 모듈방식으로 적용하였다.
여기서는 state를 적용하여 검색기능을 구현하도록 하겠다.
검색 기능 추가
input 박스의 value가 state로 관리되어야 하는데, 이 정보를 Lifting Up을 해서 부모가 state로 관리하고 자식은 이 state를 props로 내려받는다.
useState hook을 만들고 keyword와 setKeyword를 모두 props로 내린다. setKeyword는 펑션이므로 펑션을 props로 내리면 자식 컴포넌트가 펑션을 호출하면 부모컴포넌트의 펑션이 호출된다.
1 2 3 4 5 6 7 8 9 10 |
export const FilterableProductTable= () => { const [keyword, setKeyword] = useState<string>(''); return ( <div> <SearchBar keyword={keyword} setKeyword={setKeyword}></SearchBar> <ProductTable products={products}></ProductTable> </div> ) } |
리액트 훅을 사용시 type inference 가 되기 때문에 제네릭 타입으로 명시하지 않아도 된다.
SearchBar에 keyword, 와 setKeyword 타입을 정의한다.
그런데, setKeyword 타입이 웹스톰에서 마우스를 올려보면 알수 있는데, React.Dispatch<React.SetStateAction<string>> 으로 알아보기가 좀 힘들다.
이런 경우는 굳이 정확하게 타입을 해도 되지만 any 타입으로 정의하고 사용해도 무방하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
interface Props { keyword: string; setKeyword: any; } export const SearchBar: React.FC<Props> = (props) => { return ( <div> <input placeholder="Search..." value={props.keyword} onChange={(e) => props.setKeyword(e.target.value)}></input><br /> <input type="checkbox" ></input>Only show products in stock </div> ) } |
이제 검색을 하면 상태가 container 컴포넌트에 전달되므로 container 컴포넌트에서 keyword에 따라서 필터링 하도록 한다.
1 2 3 4 5 6 7 8 9 10 |
export const FilterableProductTable= () => { const [keyword, setKeyword] = useState<string>(''); return ( <div> <SearchBar keyword={keyword} setKeyword={setKeyword}></SearchBar> <ProductTable products={products.filter(item => item.name.indexOf(keyword) >= 0)}></ProductTable> </div> ) } |
재고 유무 체크 박스 구현
마찬가지로 useState hooks를 사용해서 체크박스가 체크되었는지를 체크하는 stockChecked boolean 변수와 체크하는 setStockChecked 함수를 각각 props로 내린다.
1 2 3 4 5 6 7 8 9 10 11 12 |
export const FilterableProductTable= () => { const [keyword, setKeyword] = useState<string>(''); const [stockChecked, setStockChecked] = useState(false); return ( <div> <SearchBar keyword={keyword} setKeyword={setKeyword} stockChecked={stockChecked} setStockChecked={setStockChecked}></SearchBar> <ProductTable products={products.filter(item => item.name.indexOf(keyword) >= 0))}></ProductTable> </div> ) } |
SearchBar 컴포넌트에서 타입을 추가하고 상태를 구현한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
interface Props { keyword: string; setKeyword: any; stockChecked: boolean; setStockChecked: any; } export const SearchBar: React.FC<Props> = (props) => { return ( <div> <input placeholder="Search..." value={props.keyword} onChange={(e) => props.setKeyword(e.target.value)}></input><br /> <input type="checkbox" checked={props.stockChecked} onChange={(e) => props.setStockChecked(e.target.checked)}></input>Only show products in stock </div> ) } |
체크 상태를 container 컴포넌트에 반영한다.
1 2 3 4 5 6 7 8 9 10 11 12 |
export const FilterableProductTable= () => { const [keyword, setKeyword] = useState<string>(''); const [stockChecked, setStockChecked] = useState(false); return ( <div> <SearchBar keyword={keyword} setKeyword={setKeyword} stockChecked={stockChecked} setStockChecked={setStockChecked}></SearchBar> <ProductTable products={products.filter(item => item.name.indexOf(keyword) >= 0).filter(item => stockChecked ? item.stocked : true)}></ProductTable> </div> ) } |