I use Gatsby with the MDX plugin. So I can use React components in markdown. That's fine.
I have components, talking to each other. To do this I use the Lifting State Up Pattern. That's fine.
Here is a basic Counter example, to show my proof of concept code.
import React from "react"
export class Counter extends React.Component {
constructor(props) {
super(props)
this.state = { count: 0 }
this.handleCounterUpdate = this.handleCounterUpdate.bind(this)
}
handleCounterUpdate() {
this.setState({ count: this.state.count + 1 })
}
render() {
const children = React.Children.map(this.props.children, child => {
const additionalProps = {}
additionalProps.count = this.state.count
additionalProps.handleCounterUpdate = this.handleCounterUpdate
return React.cloneElement(child, additionalProps)
})
return <div>{children}</div>
}
}
export function Display({ count }) {
return <h2>Current counter is: {count}</h2>
}
export function UpdateButton({ handleCounterUpdate }) {
return <button onClick={handleCounterUpdate}>Increment couter by one</button>
}
With this setup, one can use the components like this
<Counter>
<Display />
<UpdateButton />
</Counter>
or even like this
<Counter>
<Display />
<UpdateButton />
<Display />
<Display />
</Counter>
That's fine.
In real-world, the enclosing Counter component (state holder), will be something like a Layout component. The <Layout> is used in a template and renders the MDX pages. This looks like that:
<SiteLayout>
<SEO title={title} description={description} />
<TopNavigation />
<Display /> // The state holder is <SiteLayout>, not <Counter>
<Breadcrumb location={location} />
<MDXRenderer>{page.body}</MDXRenderer> // The rendered MDX
</SiteLayout>
The <UpdateButton> (in real-world something like <AddToCartButton>) is on the MDX page and not anymore a direct child from the <Layout> component.
The pattern does not work anymore.
How can I resolve this?
Thanks all