I've looked at what I believe may be two outdated answers given React 16's Context API.
They are:
React.js best practice regarding listening to window events from components
And:
How to implement service(concept in AngularJS) -like component in React
I'm fairly new to React, so I was wondering, given the Context API, is the correct way to do an Angular.js type of service in React (so I don't have window.addEventListener("scroll")
on every component that is listening to the scroll event, to leverage the Context API (create the event listener there?). Just wondering if I'm on the right track here...
It talks about being able to pass down props, and also about nested components being able to change the state, would it be wrong to have a wrapper component collecting the scroll position, updating the Context (scroll position), and passing that down to the needed elements? Is there a recommended way to do this and are multiple window.addEventListener("scroll")
even a problem?
I was having trouble understanding how to update the context from a nested component once it was created - in the docs here: https://reactjs.org/docs/context.html#updating-context-from-a-nested-component
So I'm not sure about updating context from a top-level/parent element and passing it down to the interior components.
You can use the context API to create a Provider with a HoC. Whenever the window size changes, the provider notify's the consumer by updating the width/height, and the consumer in the HoC, rerenders the components.
Example:
const getDimensions = () => ({
width: window.innerWidth,
height: window.innerHeight
});
const ResizeContext = React.createContext(getDimensions());
class ResizeProvider extends React.PureComponent {
state = getDimensions();
// you might want to debounce or throttle the event listener
eventListener = () => this.setState(getDimensions());
componentDidMount() {
window.addEventListener('resize', this.eventListener);
}
componentWillUnmount() {
window.removeEventListener('resize', this.eventListener);
}
render() {
return (
<ResizeContext.Provider value={this.state}>
{
this.props.children
}
</ResizeContext.Provider>
);
}
}
const withResize = (Component) => (props) => (
<ResizeContext.Consumer>
{({ width, height }) => (
<Component {...props} width={width} height={height} />
)}
</ResizeContext.Consumer>
);
const ShowSize = withResize(({ width, height }) => (
<div>
<div>Width: {width}</div>
<div>Height: {height}</div>
</div>
));
const Demo = () => (
<ResizeProvider>
<ShowSize />
</ResizeProvider>
);
ReactDOM.render(
<Demo />,
demo
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="demo"></div>
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