<script type="text/babel">
const rootElement = document.getElementById("root");
const todos = [
{ id: 1, value: "washing" },
{ id: 2, value: "running" },
{ id: 3, value: "cleaning" },
{ id: 4, value: "studying" }
];
const App = () => {
const [items, setItems] = React.useState(todos);
const handleDoneClick = (todo) => {
// items 에서 지금 누른 todo와 같지 않은 것만 다시 넣는다(filter)
// 방금 누른 값만 빼고 다시 저장한다.
setItems((items) => items.filter((item) => item !== todo));
};
const handleRestoreClick = () => {
setItems((items) => [
// todos에는 있지만(원래 있던 아이템들)
// items(state)에는 없는 것을 다시 setItems
// Done 눌러서 만든 items와 비교하는 것
...items,
todos.find((item) => !items.includes(item))
]);
};
return (
<>
{items.map((todo) => (
<div>
<span>{todo.value}</span>
<br />
<button onClick={() => handleDoneClick(todo)}>Done</button>
</div>
))}
<button onClick={handleRestoreClick}>Restore</button>
</>
);
};
ReactDOM.render(<App />, rootElement);
</script>
여기서 이런 warning이 뜬다.
unique한 key 값이 필요하다는 것.
key? value를 특정하는 이름! 우리도 지정해준 id 값이다.
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `App`. See https://reactjs.org/link/warning-keys for more information.
at div
at App (<anonymous>:39:31)
컴포넌트들을 잘 재사용하기 위해서는 unique한 id 값을 지정해주고 사용해야한다.
unique -> 중복이 없고, 바뀌지 않는 값.
ID와 PW가 둘다 값이 없으면 login 버튼을 비활성화 시킬 것이다.
<script type="text/babel">
const rootElement = document.getElementById("root");
const Id = () => {
const [id, setId] = React.useState("");
const handleIdChange = (event) => {
setId(event.target.value);
console.log("id" + event.target.value.length);
};
return (
<>
<label htmlFor="id">ID:</label>
<input type="text" id="id" onChange={handleIdChange} />
</>
);
};
const Pw = () => {
const [pw, setPw] = React.useState("");
const handlePwChange = (event) => {
setPw(event.target.value);
console.log("pw" + event.target.value.length);
};
return (
<>
<label htmlFor="pw">PW:</label>
<input type="password" id="pw" onChange={handlePwChange} />
</>
);
};
const App = () => {
return (
<form>
<Id />
<br />
<Pw />
<br />
<button type="submit" disabled={true}>
Login
</button>
</form>
);
};
ReactDOM.render(<App />, rootElement);
이렇게 했을 때, App의 자식인 <Id />
와 <Pw />
의 상태를 App은 알 수 없다.
자식(Id, Pw)의 상태를 부모에게 알릴 수 있게 상태 끌어올리기가 필요하다.
<script type="text/babel">
const rootElement = document.getElementById("root");
const Id = ({ handleIdChange }) => {
return (
<>
<label htmlFor="id">ID:</label>
<input type="text" id="id" onChange={handleIdChange} />
</>
);
};
const Pw = ({ handlePwChange }) => {
return (
<>
<label htmlFor="pw">PW:</label>
<input type="password" id="pw" onChange={handlePwChange} />
</>
);
};
const App = () => {
// Id와 Pw의 상태를 App에서 알 수 있게 끌어올렸다.
const [id, setId] = React.useState("");
const [pw, setPw] = React.useState("");
const handleIdChange = (event) => {
setId(event.target.value);
console.log("id" + event.target.value.length);
};
const handlePwChange = (event) => {
setPw(event.target.value);
console.log("pw" + event.target.value.length);
};
return (
<form>
<Id handleIdChange={handleIdChange} />
<br />
<Pw handlePwChange={handlePwChange} />
<br />
// 이제 여기서도 id와 pw의 상태를 알 수가 있게 된다.
<button type="submit" disabled={id.length===0 || pw.length===0}>
Login
</button>
</form>
);
};
ReactDOM.render(<App />, rootElement);
</script>
형제 컴포넌트의 상태가 궁금할 때, 필요하면 부모에게 lifting up 시켜서 부모도 상태를 알 수 있게 한다.
-> 하지만 과도한 lifting은 Props drilling
을 야기할 수 있다.
React.useEffect(() => {
fetch(
"https://raw.githubusercontent.com/techoi/raw-data-api/main/simple-api.json"
)
.then((response) => response.json())
.then((data) => console.log(data));
}, []);
json data fetch 하기
<script type="text/babel">
const rootElement = document.getElementById("root");
const App = () => {
const [data, setData] = React.useState(null);
const [err, setErr] = React.useState(null);
React.useEffect(() => {
fetch(
"https://raw.githubusercontent.com/techoi/raw-data-api/main/simple-api.json"
)
.then((response) => response.json())
.then((data) => {
setData(data.data);
console.log(data);
})
// 에러 catch 하는 부분
// 에러의 상태를 관리하여 에러가 발생하면 메시지를 저장한다.
.catch((err) => {
setErr(err.message);
});
}, []);
// 에러 난 상황 핸들링
if (err != null) {
return <p>에러났따.</p>;
}
// 로딩 중 상황 핸들링
if (data == null) {
return <p>Loading...</p>;
}
return (
<>
<div>
<p>People</p>
{data.people.map((person) => (
<div>
<span>name: {person.name} </span>
<span>age: {person.age}</span>
</div>
))}
</div>
</>
);
};
ReactDOM.render(<App />, rootElement);
</script>