자바스크립트 함수는 순수 함수 / 비 순수 함수로 나뉨
순수 함수는 인수에만 의존함
동일한 인수를 받으면 동일한 값을 반환함
순수 함수 예
const addOne = (n) => n + 1
이는 전역 변수에 의존할 수 있음
let base = 1
const addOne = (n) => n + base
외부에서 함수 작동 방식을 변경할 수 있어서 좋긴하지만
외부 변수에 의존한다는 사실을 모르고 다른 곳에서 사용했다간 오류 날 수도 있음
또, base 는 싱글턴 형태라 재사용성이 떨어지기도 함
const createContainer = () => {
let base = 1
const addOne = (n) => n + base
const changeBase = (b) => base = b
return { addBase, changeBase}
}
const {addBase, changeBase} = createConatiner();
이런 식으로 몽땅 감싸버리면 이제 싱글턴이 아니게 됨
재활용성이 높아짐
리액트는 상태를 ui로 변환하는 함수임 (html 리턴)
지역 상태 + useState
const AddBase = ({number}) => {
const [base, changeBase] = useState(1);
return <div>{number + base}</div>
}
이건 사실 순수하지 않음
왜냐면 changeBase로 base 값을 바꿀 수 있기 때문임
바꾸기 전엔 base를 반환하므로 순수함
이런 특성을 '멱등성(idempotent)'라고 부름
useState가 포함된 addBase 함수는 changeBase 를 함수 선언 범위 내에서만 사용할 수 있음 <= 억제 되다라고 표현함
밖에서 base 못 바꿈
컴포넌트는 억제되어 있고 이건 컴포넌트 외부에는 영향을 미치지 않음 <= 지역성 보장
이 방법은 괜찮은 방법임
---------------------------
[지역 상태 사용하면 안되는 케이스]
함수 컴포넌트 외부에서 상태를 바꿀 때임
이떄는 전역 상태가 필요함
그래도 전역 상태 막 쓰면 안됨
컴포넌트 동작 예측 어려움
지역 상태를 기본으로 사용하고
전역 상태는 보조 수단으로 쓰는 게 좋음
---------------------------
지역 상태 패턴
1. 상태 끌어올리기
부모로 끌어올려서 자식으로 보내는 거임
이때 상태는 여전히 컴포넌트 내의 지역 상태로 존재함
근데 상태를 상위 컴포넌트로 전달할 때
자식 컴포넌트를 포함해서 하위 트리 전체를 리렌더링 해서
성능 문제가 있을 수 있음
2. 내용 끌어올리기
const GrandParent = () => {
return <Parent additionInfo={<AddionalInfo/>}/>
}
const Parent = ({addinitonalInfo}) => {
const [count, setCount] = useState(0)
return (
<>
<ChildCompoenet1
count={count}
setCount={setCount}
additionInfo={AddionalInfo}
/>
<ChildCompoenet2
count={count}
setCount={setCount}
/>
</>
)
}
const ChildCompoenet1 = ({count, setCount, additionalInfo}) => {
return (
<div>
<button onClick={()=>setState(c=>c+1)}
{additionalInfo}
</div>
)
}
컴포넌트 하나 더 만들어서 컴포넌트 자체를 내려주는 방식
이렇게 하면 count가 변경될 때 리렌더링되지 않음
그냥 props로 넘겨준거니까
이걸 parent가 children을 받게해서 짜보면
const GrandParent = () => {
return (
<Parent>
<AdditonalInfo/>
<Parent>
)
}
const Parent = ({children}) => {
const [count, setCount] = useState(0)
return (
<>
<ChildCompoenet1
count={count}
setCount={setCount}
>
{children}
</ChildrenComponent1>
<ChildCompoenet2
count={count}
setCount={setCount}
/>
</>
)
}
const ChildCompoenet1 = ({count, setCount, children}) => {
return (
<div>
<button onClick={()=>setState(c=>c+1)}
{children}
</div>
)
}
훨씬 익숙한 형태...
가독성은 이게 훨씬 좋은 거 같다
+
궁금해서 chatGPT 한테 물어본 거...
끌어올리라곤 하는데...
근데 경험상 끌어올려서 예쁘게 훅으로 빼놓으면 좀 느려졌다
전역 상태
전역 상태는 지역상태가 아닌 거임
지역 상태란? 하나의 컴포넌트에 속하고 캡슐화된 상태를 지역상태라고 함
이건 좀 애매함
그러니까 모든 컴포넌트가 지역 상태가 있을 경우엔 이건 전역 상태라고 해야함..
이런 측면에서는 명확하게 나누긴 어려움
책에서는 이걸 상태가 개념적으로 속한 곳이 어디인지 보면 지역 / 전역을 알 수 있다고 하는데
그냥 감으로 알아라... 하는 거 같기도 함
전역 상태의 두가지 측면
1. 싱글턴이다
2. 공유 상태이다. (자바스크립트 메모리 상에서 단일 값일 필욘 X, 싱글턴이 아닌 전역 상태는 여러 값을 가질 수 있음)
싱글턴이 아닌 전역 상태가 작동하는 법
const createContainer = () => {
let base = 1
const addOne = (n) => n + base
const changeBase = (b) => base = b
return { addBase, changeBase}
}
const container1 = createConatiner();
const container2 = createConatiner();
container1.changeBase(10)
console.log(container1.addBase(2)) // 12
console.log(container2.addBase(2)) // 3
이건 리액트 전역 상태라기보단 그냥 클래스 비슷하게 함수 모아 놓은 형태 같은데..
책에서 만약 이처럼 전역 상태가 싱글턴이 아닐 경우 여러 값을 가질 수 있다고 한다
근데 리액트에서 전역상태 이렇게 안 쓰는데
비슷한 형태는 contextAPI 라고 했을 때 아예 state를 전역에 선언해서 싱글톤처럼 쓰는데
음..........
전역 상태 언제 쓰면 좋은가요
1. props를 전달하는 것이 적절하지 않을 때
2. 이미 리액트 외부에 상태가 있을 때
1. props를 전달하는 것이 적절하지 않을 때
트리 깊이가 깊을 때 이야기 함
3레벨에서 루트로 상태를 끌어올리는 등
이 방법은 사실 문제가 없음
지역성을 위해 권장되기도 함
그러나 상태가 변경될 때마다 하위 컴포넌트가 몽땅 렌더링되면 성능에 안 좋음
이때 전역 상태를 쓰면 추가로
props에서 벗어나 (쓸데없이 안 거쳐도 됨)
하나의 컴포넌트에서 하나의 일을 책임질 수 있어서 깔끔해짐
2. 이미 리액트 외부에 상태가 있을 때
ex) 애플리케이션에서 리액트 없이 획득한 사용자 인증 정보
전역 상태가 리액트 외부에 존재해야 함
인증 정보는 전역 상태에 저장될 수 있음
=> 전역적으로 필요한 정보들을 말하는 것 같다. 브라우저에 저장된 인증 정보는 여기저기 쓰니, 만약 브라우저에서 매번 가져오는 게 아니라 한번 가져오고 그걸 쓴다고 했을 때, 지역이 아니라 전역으로 쓰라는 거 같다 (근데 굳이,,,)
'TIL' 카테고리의 다른 글
리액트 컨택스트 (0) | 2024.04.15 |
---|---|
기초1 (0) | 2024.04.11 |
strategy template 패턴 (0) | 2024.04.11 |
useState 와 useReducer (0) | 2024.04.08 |
Iterator 패턴 (0) | 2024.03.19 |
댓글