Imagine a Container component that renders a div with the specified height, e.g.:
<Container height="80">
Hello World
</Container>

and MyHeader component that renders a Container with a certain height, e.g.:
function MyHeader() {
return (
<Container height="100">
Header content goes here
</Container>
);
}
Now, I'd like to implement a Fixed component that looks like this:
<Fixed>
<Fixed.Item>
<MyHeader />
</Fixed.Item>
<Fixed.Content>
Some content goes here
</Fixed.Content>
</Fixed>
When rendering Fixed.Content I'd like to automatically set its offset to 100px (since MyHeader is 100px high).
Is there a way for the Fixed component to get MyHeader's height so it could pass it to Fixed.Content?
Is there a better way to automate this?
Note: Using useEffect (or componentDidMount) is not an option because I'd like it to work in server rendered environments.
Generally you want data flowing down from parents to children. If that is not an option for you, you can use Contexts: https://reactjs.org/docs/context.html. Especially check out https://reactjs.org/docs/context.html#updating-context-from-a-nested-component. In your case, MyHeader could be a Consumer of your context and update it with its height, and Fixed.Content would also be a consumer that uses the value for its offset. But in general, I'd say what you're trying to do is a bit unnatural.
You can use refs for that.
To solve your specific problem, first turn your <Container> component into a class component to be able to set a ref to it.
Then use React.forwardRef to forward the ref from the MyHeader component to the <Container> component:
const MyHeader = React.forwardRef((props, ref) => {
return (
<Container ref={ref} height={100}>
Header content goes here
</Container>
);
});
Finally, create a ref hook in your component that renders the <Fixed> component and pass the ref to the <MyHeader> component. You can then also use the ref to set the height of the <Fixed.Content> component (or whatever you want to set), as follows:
function App () {
const headerRef = React.useRef(null)
return (
<Fixed>
<Fixed.Item>
<MyHeader ref={headerRef} />
</Fixed.Item>
<Fixed.Content height={headerRef.current && headerRef.current.props.height}>
Some content goes here
</Fixed.Content>
</Fixed>
)
}
This seems to only render the <App> component once, so it should also work for server-side rendering. See the following code snippet as an example: https://codesandbox.io/s/get-height-from-header-gvvlo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With