본문 바로가기
TIL

리액트 지역 상태 전역 상태

by 은지:) 2024. 4. 11.
728x90
반응형

 

자바스크립트 함수는 순수 함수 / 비 순수 함수로 나뉨

 

순수 함수는 인수에만 의존함

동일한 인수를 받으면 동일한 값을 반환함

 

순수 함수 예

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) 애플리케이션에서 리액트 없이 획득한 사용자 인증 정보

 

전역 상태가 리액트 외부에 존재해야 함

인증 정보는 전역 상태에 저장될 수 있음

 

=> 전역적으로 필요한 정보들을 말하는 것 같다. 브라우저에 저장된 인증 정보는 여기저기 쓰니, 만약 브라우저에서 매번 가져오는 게 아니라 한번 가져오고 그걸 쓴다고 했을 때, 지역이 아니라 전역으로 쓰라는 거 같다 (근데 굳이,,,)

 

 

 

 

 

728x90
반응형

'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

댓글