리액트 강의 시작 (..)
6주차 내용은 리액트 맛보기라는 주제로 강의를 구성하였는데
맛을 보니 먹을 수 있을런지의 걱정이 많이 되었다..
너무 헷갈리고 어려웠다는..
const element = <h1>hello, wolrd!</h1>
const rootElement = document.getElementById("root");
const element = <h1 className="title">Hello, world!</h1>;
ReactDOM.render(element, rootElement);
// 화면에 hello, world! 출력
!! 추가
...
const text = "hello, world!";
const titleClassName = "title123";
const element = <h1 className={titleClassName}>{text}</h1>;
...
...
const props = { className: titleClassName, children: text };
const customH1 = <h1 {...props} />;
const element = customH1;
...
// 화면에 hello, world! 출력
// 변수로 추가할 수 있음, JSX 의 강점
const rootElement = document.getElementById("root");
const paint = () => (
<>
<h1>Hi</h1>
<h3>bye</h3>
</>
);
const element = (
<>
{paint()}
{paint()}
{paint()}
</>
);
ReactDOM.render(element, rootElement);
!! 추가 : 변수를 이용하여 안에 있는 텍스트 수정
...
const paint = (title, description) => (
<>
<h1>{title}</h1>
<h3>{description}</h3>
</>
);
const element = (
<>
{paint("one", "two")}
{paint("one1", "two2")}
{paint("one2", "one2")}
</>
);
...
!! 추가 : html 태그처럼 사용 가능
...
const Paint = ({ title, description }) => (
<>
<h1>{title}</h1>
<h3>{description}</h3>
</>
);
const element = (
<>
<Paint title="one" description="two"/>
<Paint title="one1" description="two1"/>
<Paint title="one2" description="two2"/>
</>
);
// custom Element : 대문자로 작성해야함
소문자로 작성하게 되면 기본 html 태그랑 헷갈릴 수 있기 때문
...
const rootElement = document.getElementById("root");
function Number({number}){
return number % 2 === 0 ? <h1>{number}</h1> : <h3>{number}</h3>
};
const element = (
<>
<Number number={1}/>
<Number number={2}/>
<Number number={3}/>
<Number number={4}/>
</>
)
ReactDOM.render(element, rootElement);
// 화면에 2, 4만 큰 글씨로 표시됨
!! 추가 : map을 사용하여 편리하게 조건이 부합한 것에만 효과를 줄 수 있음
...
function Number({number, selected}){
return selected ? <h1>{number}</h1> : <h3>{number}</h3>
};
const element = (
<>
{[1,2,3,4,5,6,7,8,9,10].map((number) => {
<Number number={number} selected={number === 3}/>
})}
</>
)
// 화면에 숫자 3만 큰 글씨로 표시됨
//// 자바스크립트 ////
const rootElement = document.getElementById("root");
function random(){
const number = Math.floor(Math.random() * (10 - 1) + 1);
const element = `<button>${number}</button>`;
rootElement.innerHTML = element;
}
setInterval(random, 1000);
// 버튼 자체를 새로 만듬
//// 리액트 ////
const rootElement = document.getElementById("root");
function random(){
const number = Math.floor(Math.random() * (10 - 1) + 1);
const element = (
<>
<button>{number}</button>
// = <button children="{number}"/>
<div>
<p>{number}</p> // p태그 부분만 바뀜
</div>
</>
);
ReactDOM.render(element, rootElement);
}
setInteval(random, 1000);
// number가 있는 부분만 바뀜
const handleClick = () => alert("hi!");
const element = (
<button onClick={handleClick} onMouseOver={() => alert("bye")}/>
)
const rootElement = document.getElementById("root");
const state = {keyword: "", typing: false, reult: ""};
const App = () => {
function handleChange(event){
setState({typing: true, keyword: event.target.value});
}
function handleClick(){
setState({
typing: false,
result: `We find results of ${state.keyword}`
});
}
return (
<>
<input onChange={handleChange}/>
<button onClick={handleClick}>search</button>
<p>
{state.typing ? `Looking for ${state.keyword}...` : state.result}
</p>
</>
)
};
function setState(newState){
Object.assign(state, newState);
// assign: 열거할 수 있는 하나의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용
// 대상 객체를 반환하고 새로운 출처 객체를 반환
render();
}
function render(){
ReactDOM.render(<App/>, rootElement);
}
render();
리액트 검색창 예제에 useState 사용하기
...
const App = () => {
const [keyword, setKeyword] = React.useState("");
const [result, setResult] = React.useState("");
const [typing, setTyping] = React.useState(false);
function handleChange(event){
setKeyword(event.target.value);
setTyping(true);
}
function handleClick(){
setTyping(false);
setResult(`We find results of ${keyword}`);
}
return (
<>
<input onChange={handleChange}/>
<button onClick={handleClick}>search</button>
<p>
{state.typing ? `Looking for ${state.keyword}...` : state.result}
</p>
</>
)
};
...
커스텀 훅 만들기
const rootElement = document.getElementById("root");
function useLocalStorage(itemName, value = "") {
const [state, setState] = React.useState(() => {
return window.localStorage.getItem(itemName) || value;
});
React.useEffect(() => {
window.localStorage.setItem(itemName, state);
}, [state]);
return [state, setState];
}
const App = () => {
const [keyword, setKeyword] = useLocalStorage("keyword");
// useState, useEffect 기능을 하나의 함수로 묶어서 사용
const [result, setResult] = useLocalStorage("result");
const [typing, setTyping] = useLocalStorage("typing", false);
function handleChange(event) {
setKeyword(event.target.value);
setTyping(true);
}
function handleClick() {
setTyping(false);
setResult(`We find results of ${keyword}`);
}
return (
<>
<input onChange={handleChange} value={keyword} />
<button onClick={handleClick}>search</button>
<p>{typing ? `Looking for ${keyword}...` : result}</p>
</>
);
};
ReactDOM.render(<App />, rootElement);
const rootElement = document.getElementById("root");
const App = () => {
console.log("App render start");
const [show, setShow] = React.useState(() => {
console.log("App useState");
return false;
});
React.useEffect(() => {
console.log("App useEffect, no deps");
}); // 아무것도 안준건 모두에 반응
React.useEffect(() => {
console.log("App useEffect, empty deps");
}, []); // 빈 배열은 처음만 반응
React.useEffect(() => {
console.log("App useEffect, [show]");
}, [show]);
function handleClick() {
setShow((prev) => !prev); // 이전값
}
console.log("App render end");
return (
<>
<button onClick={handleClick}>search</button>
{show ? (
<>
<input />
<p></p>
</>
) : null}
</>
);
};
ReactDOM.render(<App />, rootElement);
/*
console.log
App render start
App useState
App render end
App useEffect, no deps
App useEffect, empty deps
App useEffect, [show]
*/
function Button({ props }) {
return <button className="button" {...props} />;
}
const element = (
<>
<Button className="button green" style={{ borderRadius: "50%" }}>
Green
</Button>
<Button className="button blue">blue</Button>
<Button className="button red">red</Button>
<Button className="button gray">gray</Button>
<Button className="button black">black</Button>
</>
);
ReactDOM.render(element, document.getElementById("root"));
! 동작하지 않음
왜? props 를 {props} 로 전달해주었기 때문에
객체 자체의 props는 className, style, children… 이 있는데
문자열
<style>
.button {
background-color: #4caf50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
.green {
background-color: #4caf50;
} /* Green */
.blue {
background-color: #008cba;
} /* Blue */
.red {
background-color: #f44336;
} /* Red */
.gray {
background-color: #e7e7e7;
color: black;
} /* Gray */
.black {
background-color: #555555;
} /* Black */
</style>
<script type="text/babel">
function Button({ className = "", color, style, ...rest }) {
return (
<button
className={`button ${className} ${color}`}
style={{ fontSize: 30, ...style }} // 공통적으로 넣은 것이 classname으로 넣은것보다 더 우세함
{...rest}
/>
);
}
const element = (
<>
<Button style={{ borderRadius: "50%" }}>Green</Button>
<Button
color="blue"
style={{ fontSize: 15 /*개별적으로 준게 제일 우선*/ }}
>
blue
</Button>
<Button color="button red">red</Button>
<Button color="button gray">gray</Button>
<Button color="black">black</Button>
</>
);
ReactDOM.render(element, document.getElementById("root"));
</script>
!! input에 element가 있고 화면이 뜨자마자 focus를 주고 싶다면 ?
! 자바스크립트에서는 ?.focus();
const rootElement = document.getElementById("root");
const App = () => {
React.useEffect(() => {
document.getElementById("input").focus();
}, []);
return (
<>
<input id="input" />
</>
);
};
ReactDOM.render(<App />, rootElement);
!! 어떤 값을 특정할 때 useRef로 생성되어서 만들어진 value 안에 .current로 접근가능
!! document.getElementById 로 특정 할수 있는데
리액트에서는 useRef 사용한다
const rootElement = document.getElementById("root");
const App = () => {
const inputRef = React.useRef();
const divRef = React.useRef();
React.useEffect(() => {
inputRef.current.focus();
// document.getElementById("input").focus();
setTimeout(() => {
divRef.current.style.backgroundColor = "pink";
}, 1000);
}, []);
return (
<>
<input ref={inputRef} />
<div
style={{ height: 100, width: 300, backgroundColor: "brown" }}
ref={divRef}
/>
</>
);
};
ReactDOM.render(<App />, rootElement);
const rootElement = document.getElementById("root");
const App = () => {
const handleSubmit = (event) => {
event.preventDefault();
// console.dir(event.target); // 자바스크립트의 전체 구조를 보여줌?
alert(
`FirstName: ${event.target.elements.fname.value}, LastName: ${event.target.elements.lname.value}`
);
};
return (
<form onSubmit={handleSubmit}> ! submit을 onSubmit으로 수정
<label htmlFor="fname">First name:</label>
<br />
<input type="text" id="fname" name="fname" defaultValue="John" /> // value -> defaultValue로 수정
<br />
<label htmlFor="lname">Last name:</label> // for -> htmlFor로 수정
<br />
<input type="text" id="lname" name="lname" defaultValue="Doe" />
<br />
<br />
<input type="submit" value="Submit" />
</form>
);
};
ReactDOM.render(<App />, rootElement);
const rootElement = document.getElementById("root");
const App = () => {
const [massage, setMassage] = React.useState("");
const [phoneNumber, setPhoneNumber] = React.useState("");
const handleSubmit = (event) => {
// event.preventDefalut();
alert(phoneNumber);
};
const handleChange = (event) => {
if (event.target.value.startsWith(0)) {
setMassage("phone Number is valid");
setPhoneNumber(event.target.value);
} else if (event.target.value.length === 0) {
setPhoneNumber("");
setMassage("");
} else {
setMassage("phone Number should starts with 0");
}
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="phone">PhoneNumber:</label>
<br />
<input
id="phone"
name="phone"
onChange={handleChange}
value={phoneNumber}
/>
<p>{massage}</p>
<br />
<br />
<button
type="submit"
disabled={
phoneNumber.length === 0 || massage !== "phone Number is valid"
}
>
Submit
</button>
</form>
);
};
ReactDOM.render(<App />, rootElement);
const rootElement = document.getElementById("root");
const Id = ({ handleIdChange }) => {
return (
<>
<label>ID:</label>
<input onChange={handleIdChange} />
</>
);
};
const Password = ({ handlePasswordChange }) => {
return (
<>
<label>PW:</label>
<input type="password" onChange={handlePasswordChange} />
</>
);
};
const App = () => {
const [id, setId] = React.useState("");
const handleIdChange = (event) => {
setId(event.target.value);
console.log(`id length: ${event.target.value.length > 0}`);
}; // App(부모)에게 ID 상태관리도 올려줌
const [password, setPassword] = React.useState("");
const handlePasswordChange = (event) => {
setPassword(event.target.value);
console.log(`password length: ${event.target.value.length > 0}`);
}; // App(부모)에게 PW 상태관리도 올려줌
const handleLoginClick = () => {
alert(`id: ${id}, pw: ${password}`);
};
return (
<>
<Id handleIdChange={handleIdChange} />
<br />
<Password handlePasswordChange={handlePasswordChange} />
<button
disabled={id.length === 0 || password.length === 0}
onClick={handleLoginClick}
>
Login
</button>
</>
);
};
ReactDOM.render(<App />, rootElement);