저번 시간에는 createContext,useContext를 사용한 데이터를 넘겨주는 방법을 공부했다.
오늘은 context에서 상태관리를 하는 부분을 공부해보자.
먼저 간단한 카운터를 구현하는것이다.
아래 코드를 살펴보자.
<script>
import { createContext, useContext, useState } from 'react';
const CounterContext = createContext() //context만들기
const CounterProvider = ({children})=>{
const value = useState(1)
return(
<>
{/* useState의 initialValue 1이 프로바이더의 value로 들어감 */}
<CounterContext.Provider value ={value}>
{children}
</CounterContext.Provider>
</>
)
}
const useCounterState =()=>{
const counter = useContext(CounterContext) //여기는 useState의 1이 counter에 할당됨
if(counter === "undefined"){
throw new error ("error!")
}
return counter
}
function App() {
return (
<CounterProvider>
<div>
<Counter />
<Button />
</div>
</CounterProvider>
);
}
const Counter =()=>{
const [count] = useCounterState() // useState의 값 꺼내오기
return(
<h1>
{count}
</h1>
)
}
const Button =()=>{
const [,setCount] = useCounterState() //set해서 값 변경하기
const increase = ()=>{
setCount((prev)=>prev + 1)
}
const decrease = ()=>{
setCount((prev)=>prev - 1)
}
return(
<div>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
export default App;
</script>
위코드에서 차근차근 설명해보겠다.
우리가 context에서 상태관리를 하려면 우선 provider를 따로 만들어주는게 좋다.
이유는 다음과같다.
1.중앙 집중식 상태 관리: 구성 요소 를 생성하여 CounterProvider카운터의 상태 관리를 중앙 집중화했다. 간단하게 풀어서 생각하면 카운터 상태와 관련된 데이터를 캡슐화 하기 좋기때문이다.
2.확장성: 애플리케이션이 성장하고 더 많은 전역 상태를 관리해야 하는 경우 중앙 집중식Provider를 사용하면 CounterProvider확장하기가 더 쉽다. Provider에 더 많은 상태 변수를 추가할 수 있으며 해당 상태에 액세스해야 하는 구성 요소는 추가 사용자 지정 후크를 사용할 수 있다.
위와 같은 이유로 우리는 children이라는 props를 받아 또다른 하나의 CounterProvider를 생성했다.
<script>
const useCounterState =()=>{
const counter = useContext(CounterContext) //여기는 useState의 1이 counter에 할당됨
if(counter === "undefined"){
throw new error ("error!")
}
return counter
}
</script>
위코드를 이해해보자 . useContext를 사용하여 CounterContext의 값을 counter라는 변수에 할당했다.
그리고 provider에서 값이 제대로 공급되지 않으면 undefined를 반환하기 때문에 에러를 발생하게했다.
우리는 위 커스텀훅을 사용할것이다.
counter에 할당된 값은 알고있겠지만 1이다. 하지만 그냥 1이아닌 useState의 초기값 1이다.
이게 어떤 것을 의미할까?
다음부분으로 넘어가보자.
<script>
const Counter =()=>{
const [count] = useCounterState() // useState의 값 꺼내오기
return(
<h1>
{count}
</h1>
)
}
const Button =()=>{
const [,setCount] = useCounterState() //set해서 값 변경하기
const increase = ()=>{
setCount((prev)=>prev + 1)
}
const decrease = ()=>{
setCount((prev)=>prev - 1)
}
return(
<div>
<button onClick={increase}>+</button>
<button onClick={decrease}>-</button>
</div>
)
}
</script>
위 코드를 살펴보자 우리는 useCounterState라는 custom hook을 사용하여 배열 비구조화 할당을 통해
값을 꺼내왔다. 물론 count의 값은 1일것이다.
ButtonComponent를 살펴보자.
const [,setCount] = useCounterState() 이 부분이 생소할 수 있지만 이부분은 useState에서 set함수만 사용하겠다라는 의미랑 일치한다.
그래서 업데이트 함수만 추출하여 우리가 Provider에서 공급했던 기본값 useState의 value를 업데이트 하는 로직이다.
<script>
function App() {
return (
<CounterProvider>
<div>
<Counter />
<Button />
</div>
</CounterProvider>
);
}
</script>
위와같이 CounterProvider로 컴포넌트들을 감싸주었고 CounterProvider가 return 하는 값은
<script> const CounterProvider = ({children})=>{ const value = useState(1) return( <> {/* useState의 initialValue 1이 프로바이더의 value로 들어감 */} <CounterContext.Provider value ={value}> {children} </CounterContext.Provider> </> ) } </script>이기 때문에 CounterContext.Provider value ={value}와 동일하다.
오늘은 context내에서의 상태관리를 배웠다.
https://velog.io/@velopert/react-context-tutorial#context-%EC%97%90%EC%84%9C-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%9C-%EA%B2%BD%EC%9A%B0를 참고하여 작성하였고
이해하기까지 시간이 조금 걸렸기에 내가 공부하고 이해하려는 용도로 포스팅을 하였다.