state
props
내가 좋아하는 웹사이트에서 데이터거 state/props 중 어떤 걸로 관리가 되어야 하는지 체크해보는 것도 좋다.
해당 컴포넌트의 속성이다.
function Parent() {
return (
<div className="parent">
<h1>I'm the parent</h1>
<Child name={"suri"} text={"I'm the eldest child"} />
// 그냥 문자열인 경우 중괄호를 생략해도 된다.
<Child>You can do it!</Child>
</div>
);
}
function Child(props) {
console.log("props : ", props);
return (
<div className="child">
<h1>{props.name}</h1>
<p>{props.text}</p>
<p>{props.children}></p>
</div>
);
}
export default Parent;
const App = () => {
const itemOne = "React를";
const itemTwo = "배우고 있습니다.";
return (
<div className="App">
<Learn text={itemOne + ' ' + itemTwo}/>
</div>
);
};
const Learn = (props) => {
console.log(props)
return <div className="Learn">{props.text}</div>;
};
export default App;
const props = {
name: "walli"
};
return <Hello {...props} />;
const obj = {
name : "suri",
age : 20,
};
return <Hello test={obj} />;
const Hello (props) => {
return <div>{props.test.name}</div>
}

애플리케이션의 상태이다.
리액트에서 state를 다루는 방법 중 하나로 제공하는 특별한 함수이다. 이를 통해, 함수 컴포넌트도 state 를 다룰 수 있게 되었다.
리액트로부터 useState를 불러온다. import { useState } from "react";
컴포넌트 안에서 useState를 호출한다.
const [isChcked, setIsChecked] = useState(false)
// useState의 리턴값을 구조 분해 할당한 변수이다.
// const [state 저장 변수, state 갱신 함수] = useState(상태 초기 값);
===비교===
const stateHookArray = useState(false);
const isChecked = stateHookArray[0];
const setIsChecked = stateHookArray[1];
<span>{isChecked ? "Checked" : "unChecked"}</span>
function CheckboxExample() {
const [isChecked, setIsChecked] = useState(false);
const handleChecked = (event) => {
setIsChecked(event.target.checked); // 이벤트 객체에 변경된 checked 값을 불러와 넣어준다?
};
return (
<div className="App">
<input type="checkbox" checked={isChecked} onChange={handleChecked} />
<span>{isChecked ? "Checked!!" : "Unchecked"}</span>
</div>
);
}
리렌더링된다. 즉, 화면이 업데이트 된다.
function ExampleWithManyStates() {
// 여러 개의 state를 선언할 수 있습니다!
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
<button onclick="eventHandler()">Event</button>
===비교===
<button onClick="eventHandler">Event</button>
<button onClick={() => handleClick("나는 개발자이다.")}>Click ME!</button>
폼 엘리먼트(input textarea select)는 사용자의 입력값을 받는다. 리액트에서는 이러한 변경될 수 있는 입력값을 컴포넌트의 state로 관리하고 업데이트한다.
e.target.value를 통해 이벤트 객체에 담긴 input 값을 읽어올 수 있다. function NameForm() {
const [name, setName] = useState("");
const handleChange = (e) => {
setName(e.target.value);
}
return (
<div>
<input type="text" value={name} onChange={handleChange}></input>
<h1>{name}</h1>
</div>
)
};
버튼이나 a 태그를 통한 링크 이동 등에 자주 사용되는 이벤트이다.
const [name, setName] = useState("");
const handleChange = (e) => {
setName(e.target.value);
};
return (
<div>
<input type="text" value={name} onChange={handleChange}></input>
<h1>{name}</h1>
<button onClick={() => alert(name)}>Click Me!?</button>
// alert 창을 띄우는 버튼을 추가했다.
</div>
);
}
onClick={alert(name)} 이렇게 해주면 안 된다!흠, 정리하면 이런 내용인 것 같다.
이벤트가 발생하면 이벤트 핸들러를 호출하고 그 안에서 변수 갱신 함수를 호출하면, 인자로 변화된 이벤트 객체의 값을 가져와서 state 저장 변수에 넣어준다. state 저장 변수의 값은 이벤트+이벤트핸들러에 의해 계속 바뀔 수 있는 값이다.
<Select>사용자가 drop down 목록을 열어 한 가지 옵션을 선택하면, state 변수에 갱신이 된다.
function SelectExample() {
const [choice, setChoice] = useState("som");
const members = ["som", "ming", "viho", "yoojin", "tanso"];
const options = members.map((member) => {
return <option value={member}>{member}</option>;
});
const handler = (event) => {
setChoice(event.target.value)
};
return (
<div className="App">
<select onChange={handler}>{options}</select>
<h3>You choose "{choice}"</h3>
</div>
);
}
const [showPopup, setShowPopup] = useState(false);
const togglePopup = (event) => {
let isOpen = event.target.className === 'open'
isOpen ? setShowPopup(true) : setShowPopup(false)
};
return (
<div className="App">
<h1>Fix me to open Pop Up</h1>
<button className="open" onClick={togglePopup}>Open me</button>
{showPopup ? (
<div className="popup">
<div className="popup_inner">
<h2>Success!</h2>
<button className="close" onClick={togglePopup}>
Close me
</button>
</div>
</div>
) : null}
</div>
);
}
import "./styles.css";
import { useState } from "react";
export default function App() {
// 👇 useState 두 번 사용!
// const [name, setName] = useState("");
// const [phone, setPhone] = useState("");
// const handleNameInputChange = (e) => {
// // console.log(e.target.value)
// setName(e.target.value);
// };
// const handlePhoneInputChange = (e) => {
// // console.log(e.target.value)
// setPhone(e.target.value);
// };
// 👇 하나의 객체로 관리하기!
const [userInfo, setUserInfo] = useState({
name: "",
phone: ""
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setUserInfo({
...userInfo,
[name]: value
});
};
return (
<div className="App">
<input
name="name"
placeholder={"이름을 입력해주세요"}
onChange={handleInputChange}
/>
<br />
<input
name="phone"
placeholder={"전화번호를 입력해주세요"}
onChange={handleInputChange}
/>
<br />
<button>제출</button>
<div>
<div>{`이름: ${userInfo.name}`}</div>
<div>{`휴대전화: ${userInfo.phone}`}</div>
</div>
</div>
);
}
리액트가 state를 통제할 수 있는 컴포넌트이다. input에 값 입력 시, state도 그 때 그 때 바뀌는 방식으로 통제할 수 있다. 리액트는 상태에 해당하는 데이터를 따로 관리하고 싶어한다. e.g. 트윗 전송 폼 컴포넌트

페이지를 만들기 이전에, 컴포넌트 계층 구조로 나누는 것이 가장 먼저 해야할 일이다.
데이터는 위에서 아래로 흐른다. (하향식)
리액트는 단방향 데이터 흐름을 따른다.
어떤 데이터를 상태로 두어야 할까? 3가지 질문을 통해 답을 찾자.
상태 데이터는 최소화하는 것이 바람직하다. 그렇지 않으면 앱이 복잡해진다.
하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면, 공통 소유 컴포넌트를 찾아 그 곳에 상태를 위치시킨다.
const App = () => {
const itemOne = {name : 'suri', age : 26};
return (
<div className="App">
<Learn info={itemOne} />
</div>
);
};
const Learn = ({info}) => {
return <div className="Learn">{info.name}</div>;
};
export default App;
Q. input 태그 안에 checked나 value 속성을 꼭 넣어야 하나? 넣지 않아도 구현은 되는 것 같다.
Q. 화살표 함수에서 return이 생략되는 거 조금 헷갈린다. return을 넣어주나 빼주나 그대로 실행이 된다. 흐음.
Q. 두 가지 방법 모두 arrow function 을 사용하여 함수를 정의하여야 해당 컴포넌트가 가진 state에 함수들이 접근할 수 있습니다. 화살표 함수가 아니어도 되던데..
Q. 객체의 형태로 값을 전달하고 싶을 때? 는 어떻게 하나?
Q. select 태그 안에서 option을 입력할 때, map 메소드를 활용해서 배열로 전달해도 가능한가보다. 원래 html태그에서는 그런 건 없다.
Q. const { name, value } = e.target; 객체로 데이터 관리하기에서 e.target을 구조분해 했을 때, name과 value에 각각 무엇이 담기는지? name은 value일 테고, value는 이벤트에 의해 바뀐 값이 되어야 하지 않나..