2023. 2. 9. 22:56ㆍWEB Dev/StudyNote
useReducer & useEffect
- 입력은 전체 폼의 일부이다.
- 코드가 너무 일찍 실행된 경우에는 useEffect는 state 업데이트 후에만 실행됐었다.
- 의존성은 state 전체이지 유효성이 아니다.
- 객체의 특정 속성을 추출하는 객체 디스트럭처링을 이용할 수 있다.
- const { isValid: emailIsValid } = emailState; 로 emailState의 isValid state를 emailIsVaild라는 상수로 별칭할당을 할 수 있다.
중첩 속성을 useEffect에 종속성으로 추가하기
- useEffect()에 객체 속성을 종속성으로 추가하기 위해 distructuring을 사용
const { someProperty } = someObject;
useEffect(()=>{
//code that only uses someProperty...
}, [someProperty])
- 매우 일반적인 패턴 및 접근 방식
- 핵심은 전체 개체 대신 특정 속성을 종속성으로 전달한다는 것
- 코드는 아래와 같이 작성할 수도 있지만 그것보다 위와 같이 someProperty를 종속성으로 전달하는 것을 추천한다.
- 이유는 useEffect 훅은 someObject가 변경될 때마다 재실행되기 때문이다. (someObject는 단일 속성이 아니기 때문)
useEffect(()=>{
}, [someObject])
State 관리를 위한 useReducer 대 useState
- 일반적으로 useReducer가 필요한 때는 useState를 이용하면 너무 많은 일을 처리해야 해서 번거로워질 때다.
- useState는 주요 state 관리 툴이다.
- 개별 state 및 데이터들을 다루기에 적합하다.
- state 업데이트가 쉽고 몇 개 되지 않을 때 추천한다.
- 만약 state로서의 객체나 복잡한 state가 있으면 useReducer를 고려할 수 있다.
- 연관된 state 조각들로 구성된 관련 데이터를 다루는 경우이다.
- 특히 폼이나 인풋 등의 state에 권장한다.
- state 하나를 변경하는 여러 다른 액션이 있을 때도 권장한다.
리액트 Context (Context API) 소개
- 프롭스를 통해 많은 컴포넌트를 거쳐 스테이트를 관리할 때 생기는 문제
- state를 여러 컴포넌트를 통해 전달하는 경우 props를 이용한다.
- 하위 컴포넌트들 사이에서 연속되는 관계가 없지만 state를 전달해야 할 때 모든 컴포넌트에 접근할 수 있는 가장 상위인 App 컴포넌트를 사용하게 되면서 전혀 상관없는 컴포넌트들을 거쳐 state를 전달하게 된다. -> 프롭 체인 prop chain !!!
- 부모를 통해 데이터를 전달하지 않도록 해야한다.
- 이를 위해 리액트에 내장된 내부적인 state 저장소가 있다.
리액트 컨텍스트 API 사용
- 리액트 내의 context는 state를 관리하게 해주는 거으로 앱의 어떤 컴포넌트에서 다른 컴포넌트로 직접 state를 전달하게 해준다.
- React.createContext()로 컨텍스트 객체를 생성한다.
- createContext는 기본 컨텍스트를 만든다. 대부분의 경우에 객체이다.
- 이 객체를 변수에 담아 export 하여 내보낼 수 있다.
- 리액트가 context를 사용하기 위해 해야할 일은 먼저 공급해야 하고, 접근 권한이 있어야 한다.
- 공급은 항상 첫 번째로 해야 하는 일로 그 컨텍스트를 활용할 수 있어야 하는 모든 컴포넌트를 JSX 코드로 감싸는 것을 말한다.
- JSX 코드 내에서 .을 이용해 provider에 접근할 수 있다.<AuthContext.provider>
- 이를 이용해 다른 컴포넌트 및 자손 컴포넌트는 해당 컨텍스트에 접근할 수 있다.
- 값에 접근하려면 리스닝 해야 하는데 두 가지 방법으로 리스닝 할 수 있다.
- context 소비자(Consumer) 또는 리액트 훅을 사용한다.
- 일반적으로 리액트 훅을 사용한다.
- consumer은 함수를 자식으로 가진다.
- 기본값은 공급자 없이 소비하는 경우에만 사용된다.
useContext 훅으로 컨텍스트에 탭핑(tapping)하기
- useContext 훅은 컨텍스트를 사용할 수 있게 해준다.
- 리액트 컴포넌트 함수에서 useContext를 호출하고 컨텍스트에게 사용하려는 컨텍스트를 가리키는 포인터를 전달한다.
- const ctx = useContext(AuthContext);
컨텍스트를 동적으로 만들기
- value에 함수를 가리키도록 할 수 있다.
- props는 컴포넌트를 구성하고 그것들을 재사용할 수 있도록 하는 매커니즘
- 따라서 많은 컴포넌트를 통해 전달하고자 하는 것이 있는 경우에만, 그리고 매우 특정적인 일을 하는 컴포넌트로 전달하는 경우에만 컨텍스트를 사용하는 것이 좋다.
사용자 정의 컨텍스트 제공자 구성요소 빌드 및 사용
- VSCode는 기본 context 객체를 보고 컨텍스트에서 접근할 수 있는 것을 찾기 때문에 provider value에 값을 넣더라도 기본 context 객체에 선언해주면 편하게 쓸 수 있다.
- 전체 인증 state를 별도의 공급자 컴포넌트 (auth-context.js)에서 관리할 수 있다.
리액트 컨텍스트 제한
- 리액트 컨텍스트는 앱 전체 또는 컴포넌트 전체 state에는 적합할 수 있다. (여러 컴포넌트에 영향을 미치는 state)
- 매 초 또는 1초에 여러번 state가 변경되는 경우처럼 변경이 잦은 경우에는 리액트 컨텍스트는 적합하지 않다.
- 몇 분에 한 번씩 바뀌는 경우는 컨텍스트를 쓸 수 있다.
- 앱 전체 또는 컴포넌트 전체에 걸쳐 state가 자주 변경되는 경우에는 더 나은 도구가 있다. 이것이 리덕스이다.
- 프롭의 모든 커뮤니케이션을 컨텍스트가 대체할 수 없다.
- 긴 프롭 체인을 교체하기 위해서는 고려할 만 하다.
"Hook의 규칙" 배우기
- 두 개의 메인 규칙
- 리액트 훅은 use로 시작하는 모든 함수로 리액트 훅은 리액트 함수에서만 호출해야한다. (리액트 컴포넌트 함수)
- 또는 사용자 정의 훅에서도 호출할 수 있다.
- 두 번째는 리액트 훅은 리액트 컴포넌트 함수 또는 사용자 정의 훅 함수의 최상위 수준에서만 호출해야 한다.
- 중첩문이나 block 문, 조건문, 훅 안에서 훅을 호출해서는 안된다.
- 특정 훅인 useEffect는 참조하는 모든 항목을 의존성으로 useEffect 내부에 추가해야 한다.
- useReducer 또는 useState에 의해 노출된 state 업데이트 함수는 변경되지 않도록 리액트가 보장한다.
- 브라우저에서 오지 않거나 또는 컴포넌트 함수 외부에서 오는 데이터들 외에 useEffect를 사용하는 컴포넌트 함수 내부에서 오는 데이터들은 의존성 배열로 가야 한다.
입력 컴포넌트 리팩토링
-
Forward Refs 에 대해 알아보기
- input 컴포넌트와 명령형으로 상호작용하게 해준다.
- 어떤 state를 전달해서 그 컴포넌트에서 뭔가를 변경하는 것이 아니라 컴포넌트 내부에서 함수를 호출하는 방식
- 일반적인 리액트 패턴은 아니다.
- 일반적인 input이라면 ref를 사용하면 된다.
- 함수 컴포넌트는 ref를 받을 수 없다 Function components cannot be given refs.
- 그래서 ref를 사용할 수 없고 props 객체에서 ref prop을 받아들이지 않는다.
- 제대로 작동시키기 위해서는 input 컴포넌트에서 useImperativeHandle 훅을 import 한다.
- useImperativeHandle은 컴포넌트나 컴포넌트 내부에서 오는 기능들을 명령적으로 사용할 수 있게 해준다.
- 일반적인 state 프롭 관리를 통하지 않고 부모 컴포넌트의 state로 컴포넌트를 제어하지 않고 프로그래밍적으로 컴포넌트에서 직접 호출하거나 조작하게 해준다.
- useImperativeHandle을 호출하고 두 가지를 넣어준다
- 첫 번째 인자는 컴포넌트에서 props를 받아오는 것 처럼 ref를 받아와서 넣어준다.
- 두 번째 인자인 함수에서 반환하는 것은 객체여야 하고 이 객체는 외부에서 사용할 수 있는 모든 데이터를 포함한다.
- ref 를 활성화 시키려면 input 컴포넌트 함수를 특별한 방법으로 내보내야 한다.
- React.forwardRef로 감싸준다.
const Input = React.forwardRef((props, ref) => {
const inputRef = useRef();
const activate = () => {
inputRef.current.focus();
}
useImperativeHandle( ref , ()=>{
return {
focus: activate,
}
});
return (
<div
className={`${classes.control} ${
props.isValid === false ? classes.invalid : ''
}`}
>
<label htmlFor={props.id}>{props.label}</label>
<input
ref={inputRef}
type={props.type}
id={props.id}
value={props.value}
onChange={props.onChange}
onBlur={props.onBlur}
/>
</div>
)
- 즉, 컴포넌트 함수는 forwardRef의 첫 번째 인수이다. 그리고 forwardRef는 리액트 컴포넌트를 반환한다.
- input은 여전히 리액트 컴포넌트지만 ref에 바인딩 될 수 있는 리액트 컴포넌트다.
- 포커싱 같은 곳에서 현실적으로 사용할 수 있다.
'WEB Dev > StudyNote' 카테고리의 다른 글
[React] Udemy 강의 노트 11-1 (0) | 2023.02.20 |
---|---|
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 06 (0) | 2023.02.12 |
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 05 (0) | 2023.02.05 |
[TypeScript] GraphQL과 타입스크립트로 개발하는 웹 서비스 스터디 04 (0) | 2023.01.29 |
[React] Udemy 강의 노트 10-1 (0) | 2023.01.26 |