$ yarn create react-app context-tutorial
import { createContext } from "react";
const ColorContext = createContext({color:'black'})
export default ColorContext
createContext
: 새 Context를 만들 때 사용, 기본 상태를 지정한다.
props로 받아오는 것이 아닌 Consumer라는 컴포넌트를 통해 조회를 하겠다.
import ColorContext from "../contexts/color";
const ColorBox=()=>{
return(
<ColorContext.Consumer>
{value=>(
<div
style={{
width:'64px',
height:'64px',
background:value.color
}}
/>
)}
</ColorContext.Consumer>
)
}
export default ColorBox
Consumer 사이에 중괄호를 열어서 그 안에 함수를 넣어준다.
이런 패턴을 Function as a child 혹은 Render Props 라고 부른다.
컴포넌트의 children이 있어야 할 자리에 일반 JSX 혹은 문자열이 아닌 함수를 전달한다.
Context의 value를 변경할 수 있다.
Provider를 사용할 때는 value 값을 명시해 줘야 한다
import ColorBox from './components/ColorBox';
import ColorContext from './contexts/color';
function App() {
return (
<ColorContext.Provider value={{color:'red'}}>
<>
<ColorBox></ColorBox>
</>
</ColorContext.Provider>
);
}
export default App;
context의 value에는 무조건 상태값만 있어야 하는 것이 아니다 → 함수도 가능
import { createContext ,useState } from "react";
const ColorContext = createContext({
state:{color:'black',subcolor:'red'},
actions:{
setColor : ()=>{},
setSubcolor:()=>{}
}
});
const ColorProvider = ({children})=>{
const [color,setColor] = useState('black')
const [subcolor,setSubcolor] = useState('red')
const value ={
state:{color,subcolor},
actions:{setColor,setSubcolor}
};
return (
<ColorContext.Provider value={value}>{children}</ColorContext.Provider>
)
}
const {Consumer:ColorConsumer} = ColorContext
export {ColorProvider,ColorConsumer}
export default ColorContext
ColorProvider라는 컴포넌트를 새로 작성했다.
그리고 그 컴포넌트에서는 ColorContext.Provider를 렌더링하고 있다.
이 Provider의 value에는 상태는 state로 업데이트 함수는 actions으로 묶어서 전달하고 있다.
CreateContext를 사용할 때 기본값으로 Provider의 value에 넣는 객체의 형태와 일치시키는게 좋다.
import {ColorConsumer} from "../contexts/color";
const ColorBox=()=>{
return(
<ColorConsumer>
{value=>(
<><div
style={{
width:'300px',
height:'300px',
background:value.state.color
}}
/>
<div
style={{
width:'32px',
height:'32px',
background:value.state.subcolor
}}
/>
</>
)}
</ColorConsumer>
)
}
export default ColorBox
import { ColorConsumer } from "../contexts/color"
const colors =['red','orange','yellow','blue','indigo','violet']
const SelectColors = ()=>{
return (
<div>
<h2>색을 입력하세요</h2>
<ColorConsumer>
{({actions})=>(
<div style={{display:'flex'}}>
{colors.map(color=>(
<div
key={color}
style={{
background:color,
width:'24px',
height:'24px',
cursor:'pointer'
}}
onClick={()=>actions.setColor(color)}
onContextMenu={e=>{ // 우클릭
e.preventDefault() // 우클릭시 메뉴 뜨기 막기
actions.setSubcolor(color)
}}
/>
))}
</div>)}
</ColorConsumer>
</div>
)
}
export default SelectColors
import ColorBox from './components/ColorBox';
import ColorContext, { ColorProvider } from './contexts/color';
import SelectColors from './components/SelectColors';
function App() {
return (
<ColorProvider>
<>
<SelectColors></SelectColors>
<ColorBox></ColorBox>
</>
</ColorProvider>
);
}
export default App;
import ColorContext from "../contexts/color";
import React,{useContext} from 'react'
const ColorBox=()=>{
const {state} = useContext(ColorContext)
return(
<div>
{value=>(
<><div
style={{
width:'300px',
height:'300px',
background:state.color
}}
/>
<div
style={{
width:'32px',
height:'32px',
background:state.subcolor
}}
/>
</>
)}
</div>
)
}
export default ColorBox
Redux로 넘어가면 나을수도...?