자식 컴퍼넌트에 정보를 전달하는 또 다른 방법
컴포넌트 태그에 자식함수 이름을 넣고 태그사이에 전달할 값을 입력
자식컴포넌트에서 받을때 'props로 들어오는 값.children'
function App() {
return (
<Layout>
<div>여긴 App의 컨텐츠가 들어갑니다.</div>
<div>여긴 App의 컨텐츠가 두번 들어갑니다.</div>
</Layout>
);
}
function Layout(props) {
return (
<div className="main">
<div className="header">헤더입니다</div>
{props.children}
<div className="footer">푸터입니다</div>
</div>
);
}
//헤더입니다
//여긴 App의 컨텐츠가 들어갑니다.
//여긴 App의 컨텐츠가 두번 들어갑니다.
//푸터입니다
props로 자식컴포넌트에 내려주는 값이 한개가 아닐때 좀더 쉽게 접근하는 방법
'구조분해할당 활용하기'
function App() {
const title = "제목";
const content = "내용";
return (
<div>
<h1>추출 테스트</h1>
<Todo title = {title} content = {content}/>
</div>
);
}
//일반적인 props사용
function Todo(props) {
return (
<div className="main">
<h3>{props.title}</h3>
<h3>{props.content}</h3>
투두입니다.
</div>
);
//구조분해 할당사용
function Todo(props) {
const {title, content} = props;
return (
<div className="main">
<h3>{title}</h3>
<h3>{content}</h3>
투두입니다.
</div>
);
}
//인풋값 자체에 할당하며 쓰는방법
function Todo({title, content}) {
return (
<div className="main">
<h3>{title}</h3>
<h3>{content}</h3>
투두입니다.
</div>
);
}
//추출 테스트
//제목
//내용
//투두입니다. 모든 결과값은 동일.
...
<Todo content = {content}/>
...
function Todo({title = "제목이 없습니다", content}) {
return (
<div className="main">
<h3>{title}</h3>
<h3>{content}</h3>
투두입니다.
</div>
);
}
//추출 테스트
//제목이 없습니다
//내용
//투두입니다.
컴포넌트 내부에서 바뀔 수 있는 값.
값이 변경 되야하는 상황이라면 state를 생성후 사용
state를 만들때는 useState를 사용
const [ value, setValue ] = useState( 초기값 ); //구조분해할당
//value는 state의 이름(현재상태값),
//setValue는 value값을 업데이트 할 때 사용하는 함수
//초기값을 입력하면 value 현재상태값에 초기값으 들어감.
const App = () => {
const [name, setName] = useState("기본값");
const click = ()=>{setName("바뀐값")}; //클릭하면 상태업뎃함수값을 바꿈
return (
<div>
<h1>State</h1>
{name} //현재 '기본값'
<button onClick={click}>클릭</button> //클릭시 click함수실행되면서
//'바뀐값'으로 name이 바뀜.
</div>
)
}
const App = () => {
const [value, setValue] = useState("");// state 생성
const onChangeHandler = (event) => {
const inputValue = event.target.value; //이벤트가 발생한 위치의 값을 저장
setValue(inputValue); //저장한값이 상태업뎃함수에 변경되고 value값에 할당
};
console.log(value) // value가 변할때마다, 인풋창에 값이 입력될때마다 값이 찍힘.
return (
<div>
<input type="text" onChange={onChangeHandler} value={value} />
//onChange는 인풋값이 변할때마다 onChangeHandler함수 실행됨.
//실행 될 때마다 value는 value값을 받아서 인풋창과 값을 항상 동기화되도록함
</div>
);
};
원시 데이터는 변수에 값 자체를 직접 저장.
원시 데이터의 값을 변경하면, 새로운 값이 새로운 메모리 주소에 저장되고,
변수는 이 새로운 주소를 가리킴. 그래서 불변성을 띔
참조형데이터(객체,배열 등)는 변수에 데이터값을 직접 저장하는게 아니라
그 변수값이 저장된 메모리 주소를 저장함. 그래서 변수값을 수정해도
새로운 주소를 할당하면서 값을 저장하는게(참조) 아니라서 오브젝트 내부의 값을 변경해도
오브젝트가 가리키는 메모리주소는 변하지않음. 가변성을 띔
리액트는 화면을 리랜더링 할지말지 결정할때 state의 변화를 확인함.
state의 변화를 확인하는 방법 => 메모리주소를 비교함.
그래서 참조형 데이터를 수정할 때 직접수정하면 값만 바뀌고 실제 메모리주소는 그대로.
=> 리액트가 인지못함 =>리랜더링 하지않음 =>화면에 변화 없음
function App() {
const [dogs, setDogs] = useState(["말티즈"]);
function onClickHandler() {
setDogs([...dogs, "시고르자브르종"]); // spread operator(전개 연산자)로 dogs를 펼친후
//추가해줄값 "시고르자브르종"을 펼친 dogs들 요소와 함께 setDogs에 할당
}
console.log(dogs); //초기값 "말티즈"
//
return (
<div>
<button onClick={onClickHandler}>버튼</button>
</div>
);
}
리액트의 핵심 빌딩 블록. 리액트는 컴포넌트라는 조각으로 구성됨
컴포넌트 내부에서 JSX를 통해 선언하면 화면에 출력. 리액트는 선언형 프로그래밍(선언체)
명령형 프로그래밍(DOM)
특정 작업을 수행하기 위해 컴퓨터가 해야하는 절차를 일일히 코드로 작성
선언형 프로그래밍(React)
UI가 어떻게 보여야하는지를 JSX를 통해 선언하고 render함수를 호출하면
React내부에서 어떤방식으로 할지 알아서 수행후 추상화된 절차를 통해 화면에 출력.
컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지
요청하는 작업
-triggering : UI변경후 상태변경요청
-rendering : 요청에 따른 렌더링을 함
-commit : 렌더링 결과를 출력
첫 렌더링이후 렌더링을 트리거 할려면 상태(useState 등)를 변경해주면 됨.
브라우저 렌더링 !== 리액트 렌더링
React의 렌더링이 완료되고 React가 Dom을 업데이트하면 브라우저는 화면을 출력
이 프로세서를 '브라우저 렌더링' 이라고 함.