
/** * TODO: 아래와 같은 구조로 컴포넌트를 만들고 Browser Router 설정하세요. UI는 신경쓰지 않습니다. 별도의 Router 컴포넌트 생성 여부는 자유입니다. * Home 컴포넌트는 <Link> 컴포넌트를 사용해서 Detail 컴포넌트로 이동하도록 하세요. * Detail 컴포넌트를 path parameter 로 id 를 받도록 하세요. * Detail 컴포넌트는 path parameter 로 받은 id 를 콘솔로그로 찍으세요. * * src/ |-- pages/ | |-- Home.jsx | |-- Detail.jsx |-- App.jsx */
App.jsx
function App() { return ( <BrowserRouter> <Routes> <Route path="/" element={<Home/>} /> <Route path="/detail/:id" element={<Detail/>}/> </Routes> </BrowserRouter> ); }
Home.jsx
export const Home = () => { return ( <div> <h1>Home</h1> <Link to="/detail/1">Detail</Link> </div> ) }
Detail.jsx
export const Detail = () => { const { id } = useParams(); console.log(id); return ( <div> <h1>Detail</h1> <p>Detail ID: {id}</p> </div> ); };
// Box 를 클릭하면 해당 Box만 파란색이 되도록 해야 합니다. components/ 안의 컴포넌트들안에서 TODO를 확인하세요. // TODO: GlobalStyle 컴포넌트를 만들고 styled-reset 패키지로 스타일 초기화하고 App 컴포넌트에 적용해 보세요.
App.jsx
function App() { return ( <div> <GlobalStyle/> <h1>Clickable Boxes</h1> <BoxContainer /> </div> ); }
Box.jsx
// TODO: props로 받은 $active 에 따라 배경색이 blue 또는 gray가 되도록 해보세요. const StyledBox = styled.div` width: 100px; height: 100px; background-color: ${props => (props.$active ? "blue" : "gray")}; display: flex; align-items: center; justify-content: center; cursor: pointer; color: white; font-size: 20px; `; function Box({ active, onClick }) { return <StyledBox $active={active} onClick={onClick}>Box</StyledBox>; }
BoxContainer.jsx
function BoxContainer() { const [activeIndex, setActiveIndex] = useState(0); const handleClick = (index) => { setActiveIndex(index); }; return ( <Container> {/* TODO: active prop 을 어떻게 해야 클릭한 박스임을 알수있을 지 active prop에 할당할 값을 수정해보세요. */} {[0, 1, 2, 3, 4].map((index) => ( <Box key={index} active={index === activeIndex} onClick={() => handleClick(index)} /> ))} </Container> ); }
GlobalStyle.jsx
import { createGlobalStyle } from "styled-components"; import reset from "styled-reset"; const GlobalStyle = createGlobalStyle` ${reset} `; export default GlobalStyle;
// TODO: 로컬 스토리지에서 초기 상태로 사용할 값을 가져오세요. 새로고침 해도 기존 상태를 유지하는 것이 목적입니다. // 로컬스토리지에 값이 없을 경우 빈배열[] 로 설정하세요. // TODO: 상태가 변경될 때마다 로컬 스토리지에 저장. key 값은 texts 로 합시다.
App.jsx
function App() { const initialState= JSON.parse(localStorage.getItem('texts')) || []; const [texts, setTexts] = useState(initialState); useEffect(() => { localStorage.setItem('texts', JSON.stringify(texts)); }, [texts]); const onAddText = (text) => { setTexts((prevTexts) => [...prevTexts, text]); }; return ( <div> <h1>Text Input and Listing</h1> <TextInput onAddText={onAddText} /> <ul> {texts.map((text, index) => ( <li key={index}>{text}</li> ))} </ul> </div> ); }
TextInput.jsx
function TextInput({ onAddText }) { const [inputValue, setInputValue] = useState(""); const handleChange = (e) => { setInputValue(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); if (inputValue.trim()) { onAddText(inputValue); setInputValue(""); } }; return ( <form onSubmit={handleSubmit}> <input type="text" value={inputValue} onChange={handleChange} placeholder="Enter text" /> <button type="submit">Add</button> </form> ); }