-
개발공부 34일차 [유데미 리엑트 강의]개인공부 2023. 2. 27. 23:22
JSX (리엑트에서 주로 사용하는 표현식)
리엑트는 자바스크립트 기반으로 동작한다.
컴퍼넌트 만들기
- 헤더역할을 할 컴퍼넌트 먼저 만든다.
src디렉토리 아래에 파일을 하나 생성한다. MyHeader.js - MyHeader.js 파일안에 파일을 내보낼 수 있도록 써주고
export default MyHeader;
3. app.js안에 상단에 불러와준다.
import MyHeader from './MyHeader'
4. 태그를 넣어줄 곳에 MyHeader을 넣어준다.
return ( <div className="App"> <MyHeader /> //여기에 넣어준다! <header className="App-header"> <h2>안녕 리엑트 {name}</h2> </header> </div> ); }
css주기
htnl에서는 css를 줄때 class를 class = “ “ 이렇게 줬었는데
jsx에서는 class가 자바스크립트의 예약어이기 때문에 사용이 불가하다.
css를 줄때는 className= “ “ 으로 줄 수 있다.
css파일도 import로 불러 올 수 있다.
import './App.css';
inline 스타일링
// import './App.css'; import MyHeader from './MyHeader' function App() { let name = "유리" const style = { App: { backgroundColor: "black", }, h2: { color: "red", }, bold_text: { color: "green", }, } return ( <div style={style.App}> <MyHeader /> <h2 style={style.h2}>안녕 리엑트 {name}</h2> <b style={style.bold_text} id="bord_text">React.js</b> </div> ); } export default App;
파일을 따로 이용하지 않고 함수 안에 style을 넣고 각 태그에 style을 줘서 css를 줄 수 있다.
값을 렌더링 하는방법
const number = 5; return ( <div style={style.App}> <MyHeader /> <h2 style={style.h2}>안녕 리엑트</h2> <b style={style.bold_text} id="bord_text"> {number}는 : {number % 2 === 0 ? "짝수" : "홀수"} {/* 5는 : 홀수 */} </b> </div> ); }
{ }값에는 숫자, 문자, 함수, 조건식을 넣을 수 있는데 false, [] 등 숫자나 문자열이 아닌건 렌더링이 되지 않는다.
State
컴퍼넌트가 갖는 테마처럼 계속 값이 바뀔 동적인 데이터이고 상태를 바꾸는 등의 관리는 이걸 컴퍼넌트가 직접 관리하게 된다.
import React, { useState } from "react"; const Counter = () => { // o에서 출발 // 1씩 증가하고 // 1씩 감소하는 // count상태 console.log("counter 호출!") const [count, setCount] = useState(0); //useState라는 리엑트의 메서드는 배열을 반환하고 배열의 비구조화 할당을 통해서 //0번째의 인덱스를 count로 1번째의 인덱스를 setCount로 받아왔다는 의미setCount //= count라는 상태를 변화시키는 상태변환 함수 useState의 (0)은 count의 //초기값으로 사용이 된다. //useState로 상태를 만들면 count라는 이름으로 상태의 값을 불러올 수 있는거고 //setCount라는 상태로 count를 변화시킬 수 있는거고 (0)초기값을 여기에 넣어준다. const onIncrease = () => { setCount(count + 1) } //count의 상태가 1이였을때 +버튼을 누르면 onIncrease라는 인자가 수행이 된다. //setCount가 (1 + 1)이 전달되어 2로 바뀌고 이 값이 count로 전달이되어 //count값이 2로 바뀌게 되고 <h2>{count}<h2>의 count값도 2로 바뀌게 되어 //화면에도 2로 바뀌게 된다. const onDecrease = () => { setCount(count - 1) } return ( <div> <h2>{count}</h2> <button onClick={onIncrease}>+</button> {/* html에서는 onclick = 'onIncrease()'사용했지만 리엑트에선 {}로 사용해야한다. */} <button onClick={onDecrease}>-</button> </div> ) } //count가 바뀔때마다 Counter라는 함수가 반환을 다시 한다 라고 생각 할 수 있다. export default Counter;
count가 바뀔때마다 Counter라는 함수가 반환을 다시 한다 라고 생각 할 수 있다.
이런걸 리렌더링이라고 한다.
리렌더링
함수가 자신이 가지고 있는 상태가 변화하면 함수를 다시 호출한다.
확인을 위해 console.log에 확인을 해보면 버튼을 눌러서 count값이 바뀔때마다 계속 호출이 뜨는걸 볼 수 있다.
Props
위내용의 count의 초기값을 0으로 지정해주는게 아닌 app.js가 전달하는 값으로 써야할때는 ?
initialValue={ }로 전달 할 수 있다.
return ( <div> <MyHeader /> <Counter initialValue={5} /> </div> ); }
다만 전달해야할 값이 많을때는 저렇게 사용하게되면 코드가 길어질 수 있다.
//App.js function App() { const counterProps = { a: 1, b: 2, initialValue: 5 } return ( <div> <MyHeader /> <Counter {...counterProps} /> {/* 객체 형식으로 counterProps가 전달되게 된다. */} </div> ); }
전달할 값을 따로 빼서 {…상수명}으로 전달 할 수 있다.
이렇게 전달하면 객체형식으로 전달이 되어 받아서 사용할때도 {원하는값}으로 불러올 수 있다.
import React, { useState } from "react"; const Counter = ({ initialValue }) => { //props에 initialValue의 값만 가져다 쓸 수 있다. const [count, setCount] = useState(initialValue); const onIncrease = () => { setCount(count + 1) } const onDecrease = () => { setCount(count - 1) } return ( <div> <h2>{count}</h2> <button onClick={onIncrease}>+</button> <button onClick={onDecrease}>-</button> </div> ) } Counter.defaultProps = { initialValue: 0 } //App.js에서 initialValue의 값이 지워지거나 찾지 못할때 undefined가 나오기때문에 //대비해서 넣어주는거임. 만약 진짜 지워지거나 찾지 못할때 count의 초기값은 0으로 설정된다. export default Counter;
이렇게되면 초기값을 직접 지정하지 않고 사용할 수 있다.
count의 값이 홀수인지 짝수인지 알려주게 만들기
OddEvenResult파일을 만들고 내보내준 후 Counter.js파일에 보여질 위치에 자식요소로 넣는다.
return ( <div> <h2>{count}</h2> <button onClick={onIncrease}>+</button> <button onClick={onDecrease}>-</button> <OddEvenResult count={count} /> </div> )
const OddEvenResult = ({ count }) => { //{count}라고 적은건 count는counter라는 컴포런트가 가지고 있기때문에 props로 가지고온거다. console.log(count) return <>{count % 2 === 0 ? "짝수" : "홀수"}</> } export default OddEvenResult;
count의 숫자가 바뀔때마다 짝수인지 홀수인지 나타난다.
만약 count를 넣지않고 않았을때에도 부모요소인 Counter이 리렌더 될때마다 자식요소도 리렌더되서
count가 바뀌게되면 콘솔에 RENDER!이 계속 찍힌다.
const OddEvenResult = () => { //{count}라고 적은건 count는counter라는 컴포런트가 가지고 있기때문에 props로 가지고온거다. console.log("RENDER!") //버튼을 누를때마다 RENDER이 찍히는걸 볼 수 있다. return <>{10 % 2 === 0 ? "짝수" : "홀수"}</> } export default OddEvenResult;
컴퍼넌트를 컴퍼넌트 자체로 props할 수 있다.
컴퍼넌트를 감쌀 파일을 만들고 props로 전체를 감쌀 수 있다.
//Container.js const Container = ({ children }) => { return <div style={{ margin: 20, padding: 20, border: "1px solid gray" }}> {children} {/* div값을 감싼 children */} </div> } export default Container
//App.js function App() { const counterProps = { a: 1, b: 2, initialValue: 5 } return ( <Container> <div> <MyHeader /> <Counter {...counterProps} /> </div> </Container> ); }
컴퍼넌트를 감쌀 Container파일을 만든 후 html을 감싸서 태그를 만든다.
Container컴퍼런트의 자식요소(<MyHeader />, <counter><div>) 들은 {children}이라는 props로 전달하게 된다.
{children}을 값처럼 활용을해서 style이 있는 div안에 넣어서 자식요소들이 div의 값을 다 받을 수 있다.
React 기본 - 일기장 만들어보기!
import { useState } from "react"; const DiaryEditor = () => { const [author, serAuthor] = useState("") return <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input value={author} /> </div> </div> } export default DiaryEditor;
- { useState }를 사용하기 위해 import한다.
- author의 초기값을 “ “ 공백으로 지정을 해서 input에 값을 author로 지정을해서 아무리 입력해도 serAuthor인 상태변화함수가 실행되지 않아서 공란에서 바뀌지 않는다.
import { useState } from "react"; const DiaryEditor = () => { const [author, setAuthor] = useState("") const [content, setContent] = useState("") return <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input name="author" value={author} onChange={(e) => { //값이 바뀌었을때 사용하는 이벤트 setAuthor(e.target.value) }} /> </div> <div> <textarea value={content} onChange={(e) => { setContent(e.target.value) }} /> </div> </div> } export default DiaryEditor;
onChange라는 이벤트를 이용해서 값이 입력됬을때 setAuthor로 내용이 들어가서 그값이 다시 author로 들어감으로써 input값이 입력된다.
값이 들어가는 방식은 동일하기 때문에
const [author, setAuthor] = useState("") const [content, setContent] = useState("")
위 방식을 하나로 합칠 수 있다.
import { useState } from "react"; const DiaryEditor = () => { const [state, setState] = useState({ author: "", content: "", }) return <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input name="author" value={state.author} onChange={(e) => { //값이 바뀌었을때 사용하는 이벤트 setState({ ...state, //author:state.author, content:state.content //setState()이 실행되도 author의 이벤트만 변경되고 //content의 값은 유지가 되는거다. author: e.target.value, //만약 ...state가 밑으로 오게되면 author은 변경 되었지만 다시 //author:state.author이 실행되기 때문에 값은 바뀌지 않는다. }) }} /> </div> <div> <textarea value={state.content} onChange={(e) => { setState({ ...state, content: e.target.value, }) }} /> </div> </div> } export default DiaryEditor;
이렇게 되도 동작은 하지만 이벤트핸들러가 방식이 동일한데 두개로 나눠져 있기 때문에
하나로 합칠 수 있다.
import { useState } from "react"; const DiaryEditor = () => { const [state, setState] = useState({ author: "", content: "", }) const handleChangeState = (e) => { setState({ ...state, //author:state.author //content:state.content [e.target.name]: e.target.value //author:author자리에 입력된 바뀐 값 //content:content자리에 입력된 바뀐 값 }) } return <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input name="author" value={state.author} onChange={handleChangeState} /> </div> <div> <textarea name="content" value={state.content} onChange={handleChangeState} /> </div> </div> } export default DiaryEditor;
1~5점까지 오늘의 감정점수 넣기
저장하기 버튼넣기
import { useState } from "react"; const DiaryEditor = () => { const [state, setState] = useState({ author: "", content: "", emotion: 1, }) const handleChangeState = (e) => { setState({ ...state, //author:state.author //content:state.content [e.target.name]: e.target.value //author:author자리에 입력된 바뀐 값 //content:content자리에 입력된 바뀐 값 }) } const handleSubmit = () => { console.log(state) alert("저장 성공!") //저장하기를 눌렀을때 {author: '나는', content: '일기다.', emotion: '3'} 콘솔에 찍히고 //"저장 성공!" 이라는 팝업창이 뜬다. } return ( <div className="DiaryEditor"> <h2>오늘의 일기</h2> <div> <input name="author" value={state.author} onChange={handleChangeState} /> </div> <div> <textarea name="content" value={state.content} onChange={handleChangeState} /> </div> <div>오늘의 감정점수 : <select name="emotion" value={state.emotion} onChange={handleChangeState} > <option value={1}>1</option> <option value={2}>2</option> <option value={3}>3</option> <option value={4}>4</option> <option value={5}>5</option> </select> </div> <div> <button onClick={handleSubmit}>저장하기</button> </div> </div> ) } export default DiaryEditor;
.DiaryEditor{ border: 1px solid gray; text-align: center; padding: 20px; } .DiaryEditor input,textarea{ margin-bottom: 20px; width: 500px; padding: 10px; } .DiaryEditor textarea{ height: 150px; } .DiaryEditor select{ width: 300px; padding: 10px; margin-bottom: 20px; } .DiaryEditor button{ width: 500px; padding: 10px; cursor: pointer; }
css를 넣을때는 모든 태그를 감싸고있는 최상위 태그에 className을 넣어서 그 클래스로 css를 준다.
결과 값 !
리엑트 띠용....진짜 띠용....
ㅠㅠ 너무 어렵고 프레임워크가 정해놨으니까 그대로 따라야하는건 알지만....
그걸 잘 모르겠다 하핳...자바스크립트를 못쓸거같음.....허허허...
공부하면할수록 자신감이 없어지고 ......
아니다 할 수 있 다 리 ...!!아즈아!!!
'개인공부' 카테고리의 다른 글
개발공부 40,41일차 [유데미 리엑트 강의] (1) 2023.03.10 개발공부 35일차 [유데미 리엑트 강의] (1) 2023.03.03 개발공부 32일차 [유데미 리엑트 강의] (0) 2023.02.27 개발공부 31일차 [노데미 자바스크립트 응용] (0) 2023.02.25 개발공부 29일,30일차 [유데미 자바스크립트기본 및 응용 강의] (0) 2023.02.23 - 헤더역할을 할 컴퍼넌트 먼저 만든다.