오늘도 홧팅
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App2';
import reportWebVitals from './reportWebVitals';
import App2 from "./App2";
import App3 from "./App3";
import App33 from "./App33";
import App5 from "./App5";
import App6 from "./App6";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// strict mode : 자바스크립트의 문법을 강력하게 확인한다는 의미. 자바스크립트는 간소화된 문법이다. 그렇지만 이게 있으면 좀 더 강하게 확인한다
// React.StrictMode : 배포 버전에는 제외되고 개발 버전에서는 동작하는 엄격모드, 몇 가지 함수를 중복 실행 하여 잘못된 것이 없는지 개발자에게
// 확인하도록 한다. 다 주석 처리해도 잘 실행된다
// <React.StrictMode>
//{/*/!* strict 모드란 react 앱 내의 잠재적인 문제를 알아내기 위한 도구라고 나와있습니다.*!/,*/}
//{/*/!*<App />*!/*/}
//{/*/!* <App2/>*!/*/}
//{/*/!* <App3/>*!/*/}
//{/*/!* <App33/>*!/*/}
//{/* */}
//{/*/!*</React.StrictMode>*!/*/}
// <App5/>
<App6/>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import React from "react";
import Goal from "./folder3/Goal";
import Greeting from "./folder3/Greeting";
import LoginControl from "./folder3/LoginControl";
import MailBox from "./folder3/MailBox";
import Counter from "./folder3/Counter";
import MainPage from "./folder3/MainPage";
import LandingPage from "./folder3/LandingPage";
import AttendanceBook from "./folder3/AttendanceBook";
import NameForm from "./folder3/NameForm";
import RequestForm from "./folder3/RequestForm";
import FruitSelect from "./folder3/FruitSelect";
import Reservation from "./folder3/Reservation";
import Child from "./folder3/Child";
import Parents from "./folder3/Parents";
import Parents2 from "./folder3/Parents2";
function App6() {
return(
<div className={"container"}>
<Goal isGoal = {false}/>
<hr />
<Greeting isLoggedIn = {false}/>
<hr />
<LoginControl/><hr />
<MailBox unreadMessages={50}/><hr />
<Counter/><hr />
<MainPage/><br /><hr />
<LandingPage/><hr />
<AttendanceBook/><hr />
<NameForm/>
<RequestForm/>
<FruitSelect/>
<Reservation/>
<Parents/>
<br/>
<Parents2/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</div>
)
}
export default App6;
Goal.jsx, MadeGoal.jsx, MissedGoal.jsx 파일 생성
//Goal.jsx
import React from "react";
import MadeGoal from "./MadeGoal";
import MissedGoal from "./MissedGoal";
// 조건부 렌더링 : 어떠한 조건에 따라서 화면에 표시할 렌더링이 달라지는 것.
// if문 사용 시 render() 함수가 동작하는 return 부분에서 조건문을 사용하는 것이 아니라 return 밖에서 조건문을 사용하고
// 안에서는 삼항 연산자를 사용한다.
// 자바스크립트의 true / false
// true : 논리형 true, 빈 오브젝트 타입 {}, 빈 배열 [], 0이 아닌 숫자, 빈 문자열이 아닌 문자열
// false : 논리형 false, 숫자 0 혹은 0.0, 빈 문자열 '', ``(배틱), null, undefined, NaN(Not A Number),
function Goal(props){
const isGoal = props.isGoal;
if (isGoal){ // if문은 렌더링 바깥에서 해야 한다. 렌더링 안에서 하고 싶다면 삼항연산자 사용해야한다
return <MadeGoal/>
}
return <MissedGoal/>
}
export default Goal;
//MadeGoal.jsx
import React from "react";
function MadeGoal(){
return<h1>Goal</h1>
}
export default MadeGoal;
// MissedGoal.js
import React from "react";
function MissedGoal(){
return <h2>Missed!!</h2>
}
export default MissedGoal;
로그인 버튼 누르면 다시 로그아웃버튼으로 바꾸며 글이 바뀐다
// LoginControl.jsx
import React, {useState} from "react";
import Greeting from "./Greeting";
function LoginButton (props) {
return (
<button type={"button"} onClick={props.onClick}>로그인</button>
);
}
function LogoutButton (props) {
return (
<button type={"button"} onClick={props.onClick}>로그아웃</button>
);
}
function LoginControl(props){
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 자바스크립트는 변수에 함수도 저장가능하다.
const handleLoginClick = () => {
setIsLoggedIn(true);
}
const handleLogoutClick = () => {
setIsLoggedIn(false);
}
// 엘리먼트 변수 : 자바스크립트 변수에 리액트 컴포넌트를 저장한 것
// 조건부 렌더링을 사용하기 위해서 자바스크립트 변수 button에 react 컴포넌트를 저장함
let button;
// state의 상태에 따라서 element 변수에 저장될 리액트 컴포넌트를 변경
if (isLoggedIn) {
button = <LogoutButton onClick = {handleLogoutClick}/>;
}
else {
button = <LoginButton onClick = {handleLoginClick}/>;
}
return (
<div>
<Greeting isLoggedIn = {isLoggedIn}/>
{/*엘리먼트 변수에 저장된 리액트 컴포넌트가 출력된다*/}
{button} {/*출력되는 부분. 위의 if문에 따라 모양이 달라진다.*/}
</div>
);
}
export default LoginControl;
//Greeting.jsx
import React from "react";
function Greeting(props){
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting/>
}
return <GuestGreeting/>
}
// 이렇게 써도 된다
// function Greeting(props){
// const isLoggedIn = props;
// }
function UserGreeting(){
return <h2>다시 오셨군요!!!!!</h2>
}
function GuestGreeting(){
return <h2>회원가입을 해 주세요!!</h2>
}
export default Greeting;
Mailbox.jsx Counter.jsx
&& 연산자에서 앞의 조건이 false면 뒷 부분은 아예 나오지 않는다.
app6에서 데이터를 주지 않아도 0이 출력된다.
//MailBox.jsx
import React from "react";
function MailBox(props){
const unreadMessages = props.unreadMessages;
//inline if : jsx 문법으로 렌더링을 진행하는 render()함수 내부에서 if 문을 사용할 수 없기 때문에
// '&&'를 사용하거나 삼항 연산자를 고려하여 조건부 렌더링을 진행할 수 있음
// && 연산자 사용시 && 오른쪽에 있는 피연산자는 왼쪽에 있는 피연산자의 값에 따라 렌더링이 결정된다.
// && 연산자 왼쪽의 피연산자 값이 false일 경우 오른쪽의 피연산자는 연산 평가 자체가 동작하지 않는다.
// && 연산자 왼쪽의 피연산자는 연산 평가가 이루어지기 때문에 해당 값이 그대로 출력이 된다.
return(
<div>
<h1>안녕하세요</h1>
<h3>inline if (&& 연산자 테스트)</h3>
{
unreadMessages> 0 &&
<h2>
현재 {unreadMessages}개의 읽지 않은 메세지가 있습니다.
</h2>
}
{/*{*/}
{/* unreadMessages.length> 0 &&*/}
{/* <h2>*/}
{/* 현재 {unreadMessages.length}개의 읽지 않은 메세지가 있습니다.*/}
{/* </h2>*/}
{/*원래 이랬는데, .length는 문자열만 인식하기 때문에 인식하지 못했었다*/}
{/*}*/}
</div>
);
}
export default MailBox;
// Counter.jsx
import React from "react";
function Counter(props) {
const count = 0;
//값 자체가 0 이라서 fasle다. 그렇지만 && 앞 쪽의 값이 출력된다. 화면에 0이라고 뜬다.
return(
<div>
{/*앞의 조건 false다. 데이터를 넣지 않았으니까. 그러니까 위의 0만 출력하고 끝난다.*/}
{count && <h1>현재 카운트 : {count}</h1>}
</div>
);
}
export default Counter;
삼항 연산자로 해보았다.
{
isLoggedIn ? <LogoutButton onClick={handleLogoutClick}/> : <LoginButton onClick = {handleLoginClick}/>
}
// UserStatus.jsx
import React from "react";
function UserStatus (props){
return (
<div>
이 사용자는 현재 <b>{props.isLoggedIn? '로그인' : '로그인하지 않은 '}</b> 상태입니다.
</div>
)
}
export default UserStatus;
문제 1) 아래의 소스에서 삼항 연산자를 사용한 부분을 if ~else 문을 사용하여 조건부 렌더링으로 수정하세요
// UserStatus.jsx
import React from "react";
function UserStatus (props){
// 문제 1) 아래의 소스에서 삼항 연산자를 사용한 부분을 if ~else 문을 사용하여 조건부 렌더링으로 수정하세요
//loginControl.jsx에 있다.
//만들던 즁..
// if (props.isLoggedIn = false){
// return ("로그인 하지 않은 상태입니다.")
// }
// else {
// return ("로그인한 상태입니다.")
// }
const flag = props.isLoggedIn;
if(flag){
return <p>사용자는 현재 <b>로그인</b>상태입니다.</p>
}
else {
return <p>사용자는 현재 <b>비로그인</b>상태입니다.</p>
}
// return (
// <div>
{/*이 사용자는 현재 <b>{props.isLoggedIn? '로그인' : '로그인하지 않은 '}</b> 상태입니다.*/}
// </div>
// )
}
export default UserStatus;
// WarningBanner.jsx
import React from "react";
// 컴포넌트 렌더링 막기
// 리액트에서 렌더링을 하고 싶지 않을 경우 null을 사용한다.
function WarningBanner({warning}) {
// if (!{warning}){
// return null;
// }
// return <div>경고!!</div>;
if (!warning){
return null
}
return <div>경고!!</div>;
}
export default WarningBanner;
// MainPage.jsx
import React, {useState} from "react";
import WarningBanner from "./WarningBanner";
function MainPage(props){
const [showWarning, setShowWarning] = useState(false);
const handleToggleClick = () => {
setShowWarning(prevState => !prevState);
}
return (
<div>
<WarningBanner warning={showWarning}/>
<button onClick={handleToggleClick}>{showWarning ? '감추기' : '보이기'}</button>
</div>
)
}
export default MainPage;
// Toolbar.jsx
import React from "react";
const styles = {
wrapper : {
padding : 16,
display : 'flex',
flexDirection : 'row',
borderBottom : "1px solid grey",
},
greeting : {
marginRight : 8,
},
}
function Toolbar(props){
// object 의 확장표현식으로 props 객체에 있는 데이터를 모두 받음
const {isLoggedIn, onClickLogin, onClickLogOut} = props;
return (
<div style = {styles.wrapper}>
{/* &&연산자로 isLoggedIn의 값에 따라 화면 렌더링 여부 결정*/}
{isLoggedIn && <span style={styles.greeting}>환영합니다.</span>}
{/*삼항 연산자로 로그인/로그아웃 버튼을 출력*/}
{isLoggedIn
? (<button onClick={onClickLogOut}>로그아웃</button> )
: (<button onClick={onClickLogin}>로그인</button>)
}
</div>
);
}
export default Toolbar;
// LandingPage.jsx
import React,{useState} from "react";
import Toolbar from "./Toolbar";
function LandingPage(props){
// isLoggedIn을 state로 설정
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 클릭 이벤트 시 사용할 함수를 생성
// state 값 수정을 위한 함수 생성
const onClickLogin = () => {
setIsLoggedIn(true);
}
const onClickLogOut = () => {
setIsLoggedIn(false);
}
return (
<div>
{/*{{onClickLogOut}에 들어있는건 위에 있는 함수이다. 위에서 받아와서 랜팅페이지에서 넘겨줘서stae값 변경해주는 걸 이 페이지에서
대신 해주고 있음}*/}
<Toolbar isLoggedIn={isLoggedIn} onClickLogin={onClickLogin} onClickLogOut={onClickLogOut}/>
<div style={{padding : 16}}>베너 확인</div>
{/* {{padding : 16}} 바깥 {}는 데이터를 집어넣기 위해 안의 {}는 js의 오브젝트라는 걸 알려줌*/}
</div>
)
}
export default LandingPage;
//AttendenceBook.jsx
import React from "react";
// 앞으로 리스트로 데이터를 넣거나 가져올 때 key 부분을 만들어라. 구분할 수 있는 유일한 값이면 된다.
const students = [
{id : 1, name : "Inje"},
{id : 2, name : "Steve"},
{id : 3, name : "Bill"},
{id : 4, name : "Jeff"},
];
// 리스트 : 비슷한 데이터를 모아둔 것
// key : 리액트에서 각 객체나 아이템을 구분할 수 있는 고유의 값. key가 없으면 서로 구분할 수 없다.
// react에서는 해당 리스트 사이에서 엘리먼트를 구분할 수 있는 고유한 값이면 된다.
// id를 사용, id라는 것 자체가 고유한 값이라는 의미이므로 key값으로 사용할 수 있다.
function AttendanceBook(){
return(
<ul>
{students.map((student)=>{
return <li>{student.name}</li>
})}
</ul>
);
}
export default AttendanceBook;
칸에 내용을 넣어 제출 버튼 누르면 alert로 그 내용이 뜬다.
//NameForm.jsx
// 텍스트 박스를 이용한 이벤트
import React, {useState} from "react";
function NameForm(props){
//변수 value를 state로 설정, 기본값은 빈 문자열.
const [value, setValue] = useState(''); //기본값을 비웠다
// event 발생 시 동작하는 함수
// 매개변수로 자바스크립트의 event 객체를 가져온다.
// 실제 이벤트가 발생한 태그의 정보가 담겨져 있다.(input 태그)
const handleChange = (event) => {
//state로 설정된 변수 value의 값을 변경하는 setValue() 함수 실행
// 여기서 event는 자바스크립트 이벤트 객체다.
// target => 이벤트를 발생시킨 대상 찾아온다
// 객체를 통해서 이벤트가 발생한 대상에 대한 정보를 가져옴
//이름을 치면 값이 변경되니까 이벤트가 발생해서 여기로 온다.
// value : 이벤트가 발생하면서 생긴 값을 가져와라
// 이벤트 발생 대상이 가지고 있는 value 값을 사용하여 state를 변경
setValue(event.target.value);
}
// submit 버튼에 이벤트가 발생되면 실행하라
const handleSubmit = (event) => {
alert("입력한 이름 : " + value);
event.preventDefault();
}
return(
<form onSubmit={handleSubmit} className={"container"} action={"#"}>
<div className={"my-3"}>
<label for = {"user-name"} className={"form-label"}>이름 : </label>
{/*input 태그 부분이 중요함*/}
{/* input 태그의 value를 state로 설정된 변수를 사용하여 화면에 데이터를 출력 */}
{/* 사용자 입력에 의해서 값이 변경될 경우 event를 발생한다 (onChange)*/}
<input type={"text"} className = {"form-control"} value={value} onChange={handleChange}/>
</div>
<div className = {"my-3"}>
<button type={'submit'} className={"btn btn-primary"}>제출</button>
</div>
</form>
);
}
export default NameForm;
//RequestForm.jsx
// textarea 사용하기
import React, {useState} from "react";
function RequestForm(props) {
const [value, setValue] = useState("요청 사항을 입력하세요")
//이거 넣어준거밖에 없음
const handleChange = (event) => {
setValue(event.target.value);
}
const handleSubmit = (event) => {
alert('입력한 요청사항 : ' + value);
event.preventDefault(); //화면 재랜더링하는 것을 막아준다.
}
return(
<form onSubmit={handleSubmit} className={"container"}>
<div className={"my-3"}>
{/*!!!!!!반드시!! onChange를 넣어줘야합니다!!! 이거 없으면 수정이 안됩니다!! 기존값만 계속 나타날거다.!!!!!*/}
<label for={"user-contents"} className={"form-label"}>요청사항 : < / label >
<textarea value={value} className={'form-control'} onChange={handleChange}/>
</div>
<div className={"my-3"}>
<button type={"submit"} className = {"btn btn-primary"}>제출</button>
</div>
</form>
)
}
export default RequestForm;
아래에 있는 건 다중선택이 가능하다.
//FruitSelect.jsx
import React, {useState} from "react";
function FruitSelect(props){
const [value, setValue] = useState('grape');
const [value2, setValue2] = useState([]);
const handleChange=(e)=>{
setValue(e.target.value);
}
// 배열로 넣어주기
const handleChange2=(e)=>{
// select box 의 자식 태그인 option 태그를 모두 가져옴
const options = e.target.options;
// 선택된 데이터를 저장하기 위한 배열
let items = [];
// option의 크기 만큼 반복
for (let i=0; i < options.length; i++){
// option태그 중 선택된 태그인지 아닌지 확인
if(options[i].selected){
// 선택된 태그의 내용만 배열에 저장
items.push(options[i].value);
}
}
// setState() 함수를 통해서 state 업데이트
setValue2(items);
}
const handleSubmit = (e) => {
alert(`선택한 과일 : ${value} 다중선택한 과일 : ${value2}`);
e.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<div className={"my-3"}>
<label for={"sel1"} className={"form-label"}>과일을 선택하세요 : </label>
{/*select 사용 시 기본 값 설정 value 속성으로 진행*/}
{/*multiple 속성 사용 시 true/false 사용. html에서는 multiple만 썼었음*/}
{/*리액트에서 기본 html의 속성 중 속성명으로만 효과가 발생하는 속성에 대해서도 값을 제어하기 위해서
속성명 = {값} 형식으로 사용함 */}
<select id={"sel1"} className={"form-select"} value={value} onChange={handleChange} disabled = {false}>
<option value={"apple"}>사과</option>
<option value={"banana"}>바나나</option>
<option value={"grape"}>포도</option>
<option value={"watermelon"}>수박</option>
</select>
<br/>
<div className = {"my-3"}>
<label for = {"sel2" } className={"form-label"}>과일을 선택해주세요</label>
<select id={"sel2"} className={"form-select"} onChange={handleChange2} value={value2} multiple={true}>
<option value={"apple"}>사과</option>
<option value={"banana"}>바나나</option>
<option value={"grape"}>포도</option>
<option value={"watermelon"}>수박</option>
</select>
</div>
</div>
<div className={"my-3"}>
<button type={"submit"} className={"btn btn-primary"}>제출</button>
</div>
</form>
)
}
export default FruitSelect;
아침식사 여부 옆의 체크박스로 true / false 값이 출력된다.
// Reservaton.jsx
import React, {useState} from "react";
function Reservation(props) {
const [haveBreakfast, setHaveBreakfast] = useState(true);
const [numberOfGuest, setNumberOfGuest] = useState(2);
const handleSubmit = (e) => {
alert(`아침 식사 여부 : ${haveBreakfast}, 방문객 수 : ${numberOfGuest}`);
e.preventDefault();
}
return(
<form onSubmit={handleSubmit}>
<div className={"my-3"}>
<label className={"form-label"}>아침식사 여부 : </label>
<input type={"checkbox"} checked={haveBreakfast} onChange={(e)=>{
setHaveBreakfast(e.target.checked);
}}/>
</div>
<div className = {"my-3" }>
<label className={"form-label"}>방문객 수 : </label>
<input type={"number"} value={numberOfGuest} onChange={(e)=>{
setNumberOfGuest(e.target.value);
}}/>
</div>
<div className={"my-3"}>
<button type={"submit"} className={"btn btn-primary"}>제출</button>
</div>
</form>
);
}
export default Reservation;
// Parents.jsx
// 부모 컴포넌트
import React from "react";
import Child from "./Child";
function Parents(props){
return(
<div>
<h1>Parents 컴포넌트 영역</h1>
<Child value={"부모 데이터"}/>
</div>
)
}
export default Parents;
// Child.jsx
// 자식 컴포넌트 Parents.jsx의 자식이다.
import React from "react";
function Child(props){
return(
<div>
<h3>Child 컴포넌트 영역</h3>
<p>전달받은 값 : {props.value}</p>
</div>
)
}
export default Child;
// Parents2.jsx
// 부모 컴포넌트
import React, {useState} from "react";
import Child2 from "./Child2";
function Parents2(props){
// childData를 state로 설정
const [childData, setChildData] = useState('');
return(
<div>
<h1>Parents2 컴포넌트 영역</h1>
{/*자식 컴포넌트 호출*/}
{/*자식 컴포넌트 호출 시 value, childValue라는 키에 데이터를 저장해서 전달*/}
{/* childValue 키에 setState() 함수를 저장해서 전달 */}
<Child2 value={"부모 데이터2"} childValue ={setChildData}/>
{/* 현재 state 중 childData 변수를 화면에 출력 */}
<h3>Child2컴포넌트에서 전달받은 데이터 : {childData}</h3>
</div>
)
}
export default Parents2;
//Child2.jsx
import React from "react";
// Child2 컴포넌트는 부모 컴포넌트에서 전달받은 2개의 키가 존재함
// props에 value, childValue 키를 전달 받았고, 해당 키에 1:1로 매칭된 데이터가 존재한다.
// value : "부모 데이터", childValue : setState() 함수가 들었음
// 자식 => 부모 : 부모 컴포넌트가 제공하는 키에 부모가 사용하고 있는 함수에 데이터를 넣어준다.
// 부모는 자기 함수를 실행하면서 전달받은 데이터가 실행이 된다.
// 부모가 넘겨줄 때 이름은 childValue고 실제 부모가 사용할 때는 childData가 실행된다.
function Child2(props){
// 부모 컴포넌트에서 props를 통해서 전달받은 함수를 실행
// 부모 컴포넌트에서 전달받은 함수가 부모의 state를 수정할 수 있는 setState()함수임
const sendData = () => {
props.childValue('자식 데이터');
}
return(
<div>
<h3>Child2 컴포넌트 영역</h3>
{/*부모 컴포넌트에서 props를 통해서 전달받은 데이터 출력*/}
<p>부모 컴포넌트에서 전달받은 데이터 : {props.value}</p>
{/*버튼 클릭 시 지정한 함수 실행 - 버튼 클릭 이벤트*/}
<button onClick={sendData} className={"btn btn-primary"}>클릭 시 데이터 전달</button>
</div>
)
}
export default Child2;
부모컴포넌트 부모의 state에 setState를 자식 컴포넌트에 전달. 자식 컴포넌트는 부모의 setState를 실행할 수 있다. =>