hyben09 / udemy-react Goto Github PK
View Code? Open in Web Editor NEWudemy-react 학습 저장소
udemy-react 학습 저장소
Input 컴포넌트는 ref 프롭을 가지고 내부적으로 아무것도 하지 않습니다. props 객체에서 ref 프롭을 받아들이지 않습니다
그 안 어디에서도 props.ref를 사용하지 않습니다 하지만 사용하더라도, ref는 일종의 예약어입니다.
제대로 작동시키는 방법이 있습니다 두 가지만 하면 됩니다
하나는 Input 컴포넌트에서 다른 훅을 임포트하는 겁니다. useImperativeHandle 훅입니다
이 훅을 사용하면 컴포넌트나 컴포넌트 내부에서 오는 기능들을 명령적으로 사용할 수 있게 해줍니다
즉 일반적인 state 프롭 관리를 통하지 않고 부모 컴포넌트의 state를 통해 컴포넌트를 제어하지 않고
프로그래밍적으로 컴포넌트에서 무언가를 직접 호출하거나 조작해서 사용하게 해주는 것 입니다.
⛔️useImperativeHandle 훅은 거의 사용하지 않을것. 따라서 프로젝트에서도 자주 사용하면 안 됩니다.
useEffect(() => {
const identifier = setTimeout(() => {
console.log("Checking form validity!");
setFormIsValid(emailState.isValid && passwordState.isValid);
}, 500);
return () => {
console.log("CLEANUP");
clearTimeout(identifier);
};
}, [emailState, passwordState]);
➡️ 별칭 할당
const { isValid: emailIsValid } = emailState;
const { isValid: passwordIsValid } = passwordState;
useEffect(() => {
const identifier = setTimeout(() => {
console.log("Checking form validity!");
setFormIsValid(emailIsValid && passwordIsValid);
}, 500);
return () => {
console.log("CLEANUP");
clearTimeout(identifier);
};
}, [emailIsValid, passwordIsValid]);
값만 변경되고 유효성은 변경되지 않으면이 이펙트는 다시 실행되지 않습니다.
뭔가를 입력하면 초반에는 실행됩니다 그러나 일단 비밀번호가 유효하면 문자가 하나 더 있더라도 유효성 출력에서 추가 확인이 일어나지 않습니다.
useEffect를 더욱 최적화하고 이펙트가 불필요하게 실행되는 것을 피하기 위해서 입니다.
만약 하나씩 증가하는 카운터를 관리하고 있다면 상태를 업데이트할 때마다 그래서 이 객체에서 우리가 하는 것처럼 이런 식으로 하면 안됩니다
리액트가 상태 업데이트 스케줄을 갖고 있어서 바로 실행하지 않는다.
그래서 이론적으로 동시에 수많은 상태 업데이트를 계획한다면 오래되었거나 잘못된 상태 스냅샷에 의존할 수도 있습니다
상태를 업데이트하는 함수를 위한 대체 폼을 사용해야 합니다
호출하는 대신 호출해서 그 함수에 함수를 전달해야 합니다 그래서 setUserInput함수를 호출해서 함수를 전달
setUserInput((prevState) => {
return { ...prevState, enteredTitle: e.target.value };
});
리액트는 이 안에 있는 함수에서 이 상태 스냅샷이 가장 최신 상태의 스냅샷이라는 것과 항상 계획된 상태 업데이트를 염두에 두고 있다는 것을 보장할 것입니다
그래서 이것은 항상 최신 상태의 스냅샷에서 작업하도록 하는 좀더 안전한 방법입니다.
props drilling이란
Props drilling은 React에서 발생하는 문제 중 하나로, 컴포넌트가 필요로 하는 데이터가 자식 컴포넌트까지 계속해서 전달되는 현상을 말합니다. 이로 인해 컴포넌트 구조가 복잡해지고, 유지 보수가 어려워지는 문제가 발생할 수 있습니다.
일반적으로 데이터는 프롭을 통해 컴포넌트에 전달됩니다
하지만 항상 문제가 되는 건, state를 여러 컴포넌트를 통해 전달하는 경우입니다
즉 기본적으로는 프롭을 활용하여 다른 컴포넌트에 데이터를 전달합니다.
const MainHeader = (props) => {
return (
<header className={classes['main-header']}>
<h1>A Typical Page</h1>
<Navigation isLoggedIn={props.isAuthenticated} onLogout={props.onLogout} />
</header>
);
};
MainHeader에서는 그 두 가지 프롭 중 어느 것도 사용되지 않습니다
Navigation 컴포넌트에 다시 전달하는 용도로만 사용되고 있습니다
만약 앱이 크다면, 전달하는 경로가 점점 더 길어질 수 있습니다.
해결법 ➡️ React Context 사용
React Context를 사용하여 데이터를 전역적으로 관리하는 방법입니다. React Context를 사용하면, 데이터를 중간 컴포넌트를 거치지 않고도 하위 컴포넌트에서 바로 사용할 수 있습니다. 이를 통해 컴포넌트 구조를 단순화하고, 유지 보수성을 향상시킬 수 있습니다.
ExpenseItem 컴포넌트 함수가 실행될 때마다 호출될 것입니다
그래서 만약 다시 로드하면, 네 번 호출 왜냐하면 이 Expenses에서 ExpensesItem을 네 번 사용했기 때문입니다
이 컴포넌트의 독립적인 네 개의 인스턴스가 생성됩니다
하지만 만약 ExpenseItem에 있는 Change Title 버튼 중 하나를 클릭하면
단 한번만 출력되는 것을 볼 수 있는데 그것은 기본적으로 벌어지는 일입니다
즉 단지 그 특정 인스턴스만 업데이트되었기 때문에 다시 평가된 것이고
다른 인스턴스들은 상태 변화에 영향을 받지 않습니다.
State는 컴포넌트의 인스턴스별로 나뉘어져 있습니다.
새로운 값을 할당할 때 왜 상수형을 사용하는 걸까요?
등호를 사용해서 값을 할당하지 않는다는 것
절대 등호 연산자로 title에 새로운 값을 할당하지 않습니다 그래서 상수형을 써도 괜찮습니다
컴포넌트형 함수에서는 state가 업데이트되면 재 실행된다는 것
그래서 setTitle를 호출해서 새로운 title을 할당하면 이 컴포넌트를 다시 불러오게 되고
이 업데이트된 title은 우리를 위해 state를 관리하는 리액트에서 가져온 것입니다.
기본적으로는 리액트에게 “이봐, 관리하라고 했던 최신 제목 상태를 이제 줘” 라고 하는 것
리액트는 useState가 반환하는 배열에서 가장 최신의 상태를 우리에게 제공합니다
그래서 이 컴포넌트가 재실행될 때마다 우리는 항상 가장 최신 상태의 화면을 갖습니다
props.title로 다시 어떤 state의 변화를 덮어쓰는 것은 아닐까 라고 생각할 수도 있습니다
리액트는 처음으로 주어진 컴포넌트 인스턴스에서 useState를 호출할 때 기록한다는 것입니다
그래서 우리가 처음 호출할 때 해당 인자를 초깃값으로 취합니다
하지만 만약 컴포넌트가 그때 재실행되면 상태가 변했기 때문에 리액트는 state를 다시 초기화하지는 않을 것입니다
대신, 이전에 상태가 초기화됐던 것을 추적해서 예를 들면, 어떤 state가 업데이트된 것에 기반해서
가장 최신의 state를 대신 우리에게 제공할 것입니다
그래서 이 초깃값은 주어진 컴포넌트 인스턴스에 대해 처음으로 이 컴포넌트형 함수가 실행될 때만 고려되는 값
const toggleParagraphHandler = useCallback(() => {
if (allowToggle) {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}
}, [allowToggle]);
const allowToggleHandler = () => {
setAllowToggle(true);
};
React에서 setState 메소드에 함수를 전달하는 경우는 두 가지입니다.
이전 상태(previous state)에 기초한 새로운 상태(new state)를 계산할 때
예를 들어, 이전 상태를 사용하여 새로운 배열을 필터링하거나 매핑하거나 정렬하는 경우입니다.
비동기적 업데이트(asynchronous updates)를 실행할 때
예를 들어, 이전 상태를 사용하여 서버에서 데이터를 가져오는 경우입니다.
이러한 경우 setState 메소드에 함수를 전달하는 것이 좋습니다.
왜냐하면 setState 메소드는 비동기적으로 작동하기 때문에,
이전 상태가 변경되기 전에 여러 setState 호출이 배치될 수 있습니다. 이전 상태(previous state)에 의존하는 함수를 전달하면, 해당 함수는 이전 상태를 가져와서 정확한 값을 계산할 수 있습니다.
즉, 동시에 여러 번의 갱신이 스케줄될 수 있으므로 상태를 갱신할 때는 함수 형태를 이용해서 갱신하는 것을 추천
(이전 상태의 스냅샷에 의존해야 한다면 특히 )
const [enteredTitle, setEnteredTitle] = useState("");
const [enteredAmount, setEnteredAmount] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const titleChangeHandler = (e) => {
setEnteredTitle(e.target.value);
};
const amountChangeHandler = (event) => {
setEnteredAmount(event.target.value);
};
const dateChangeHandler = (event) => {
setEnteredDate(event.target.value);
};
세 state는 기본적으로는 같은 개념이 세 번 반복된 것입니다
따라서, 세 번의 state 대신 state 한번으로 가도 됩니다.
const [userInput, setUserInput] = useState({
enteredTitle: "",
enteredAmount: "",
enteredDate: "",
});
const titleChangeHandler = (e) => {
// setEnteredTitle(e.target.value);
setUserInput({
...userInput,
enteredTitle: e.target.value,
});
};
const amountChangeHandler = (e) => {
// setEnteredAmount(event.target.value);
setUserInput({
...userInput,
enteredAmount: e.target.value,
});
};
const dateChangeHandler = (e) => {
// setEnteredDate(event.target.value);
setUserInput({
...userInput,
enteredDate: e.target.value,
});
};
state를 업데이트할 때마다 한 개가 아니라 이 세 프로퍼티 모두를 업데이트해야 한다는 차이점이 있다.
만약 새로운 사용자 입력을 이 객체에 설정한다면 기본적으로 다른 키들은 버리게 됩니다
왜냐하면 state를 업데이트할 때 리액트는 이것을 이전 state와 병합하지 않기 때문입니다.
단순히 예전 state를 새 것으로 대체합니다
그래서 만약 새로운 state가 하나의 키와 값의 쌍을 갖는 객체라면 이전 state는 대체되고
Amount와 date를 위한 키와 값의 쌍은 잃어버리게 될 것입니다
그래서 만약 하나의 state로 접근하고 하나의 객체를 관리한다면 모든 데이터가 사라지지 않도록 해야 합니다
그러기 위해서는 여기서 업데이트하지 않는 다른 값들을 수동으로 복사해야합니다.
이때, 스프레드 연산자를 사용합니다.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.