Am making a website using Gatsby. Am using styled components as well.
For a certain page the designers in their infinite wisdom have decided that a certain button should 1) SHow at the top of the page for desktop 2) Show at the bottom of the page for mobile. Since I am already deep into the project I did not want to go about positioning everything with absolute. As other things will break. So I tried this.
const SizeDetector = styled.div`
height: 0px;
width: 100%;
background-color: ${props => {
props.detectDesktopAndTablet()
return 'white'
}
}
@media (max-width: 450px) {
background-color: ${props => {
props.detectMobile()
return 'white'
}
}
}
`
class ContextualFrame extends React.Component {
constructor() {
super();
this.detectMobile = this.detectMobile.bind(this);
this.detectDesktopAndTablet = this.detectDesktopAndTablet.bind(this);
this.detectDesktopAndTablet = this.detectDesktopAndTablet.bind(this);
this.state = {'mobile': false, 'hasMounted': false}
}
detectMobile() {
this.setState({'mobile': true})
}
detectDesktopAndTablet() {
console.log('here')
this.setState({'mobile': false})
}
componentDidMount() {
this.setState({'hasMounted': true})
}
render() {
let {mobile, hasMounted} = this.state
return (
<div>
{
hasMounted ? (<SizeDetector detectDesktopAndTablet={this.detectDesktopAndTablet} detectMobile={this.detectMobile} />) : null
}
{
mobile ? null : (<MeetPeopleButton text={'Meet The Team'} />)
}
{this.props.children}
{
mobile ? (<MeetPeopleButton text={'Meet The Team'} />) : null
}
</div>
)
}
}
This is causing an error:
RangeError: Maximum call stack size exceeded
The 'here' in the console log in the detectDesktopAndTablet is being called thousands of times.
Why is this happening? I guess that this might be happening due to some particular way that either Styled Components or React work. Asking to increase my understanding of how React works.
Maybe I've figured out your problem. It is that during the render, you are changing your component's state, making it render again, and so on:
ContextualFrame.render()
-> calls SizeDetector.render()
-> calls detectDesktopAndTablet()
-> calls setState(...)
-> procs ContextualFrame.render()
To fix this, checks if the property is the same before setting it:
detectDesktopAndTablet() {
console.log('here')
if(this.state.mobile !== false) this.setState({'mobile': false})
}