ネストしたときに一番近いものを参照できていいんだけど あるイベントが起きた回数を共有するみたいなときに最も近いコンテキストだけじゃなくて更に上にも伝わってほしい
標準の仕組みでそういうことをするものはなさそうなので 自分でそうなるように作る
基本の形
const CounterContext = createContext()
const CounterProvider = CounterContext.Provider
const useCounter = () => useContext(CounterContext)
const useNewCounter = () => {
const [count, setCount] = useState(0)
return {
count,
up: () => setCount(x => x + 1)
}
}
const Parent = () => {
const counter = useNewCounter()
return (
<CounterProvider value={counter}>
<Button />
<hr />
<Child />
<hr />
<Button />
</CounterProvider>
)
}
const Child = () => {
const counter = useNewCounter()
return (
<CounterProvider value={counter}>
<Button />
<Button />
</CounterProvider>
)
}
const Button = () => {
const counter = useCounter()
return (
<button onClick={counter.up}>{counter.count}</button>
)
}
単純にネストしただけなので これだと Child の中のボタンを押しても Child のカウンターしか増えない
Child をこうして Parent のカウンターの up も呼び出す
const Child = () => {
const counter = useNewCounter()
const parent_counter = useCounter()
const chain_counter = {
...counter,
up: () => {
counter.up()
parent_counter.up()
},
}
return (
<CounterProvider value={chain_counter}>
<Button />
<Button />
</CounterProvider>
)
}
毎回書きたくないのでフックにまとめる
const useChainCounter = () => {
const parent_counter = useCounter()
const counter = useNewCounter()
return {
...counter,
up: () => {
counter.up()
parent_counter?.up()
}
}
}
const Child = () => {
const chain_counter = useChainCounter()
return (
<CounterProvider value={chain_counter}>
<Button />
<Button />
</CounterProvider>
)
}