Optimize array of component which have window event listeners
I have array of data, which needed to render array of one and the same component which has window event listener. But if we have 20 event listeners on page then we have super freezing on page. How to have one event listener on array of one and the same component?
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
Edited with code example. I use this component for displaying or hiding button if it not fit in window. I comment place where i create eventListeners
reactjs optimization addeventlistener event-listener
add a comment |
I have array of data, which needed to render array of one and the same component which has window event listener. But if we have 20 event listeners on page then we have super freezing on page. How to have one event listener on array of one and the same component?
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
Edited with code example. I use this component for displaying or hiding button if it not fit in window. I comment place where i create eventListeners
reactjs optimization addeventlistener event-listener
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
@AKX ready. added
– Marty
yesterday
1
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday
add a comment |
I have array of data, which needed to render array of one and the same component which has window event listener. But if we have 20 event listeners on page then we have super freezing on page. How to have one event listener on array of one and the same component?
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
Edited with code example. I use this component for displaying or hiding button if it not fit in window. I comment place where i create eventListeners
reactjs optimization addeventlistener event-listener
I have array of data, which needed to render array of one and the same component which has window event listener. But if we have 20 event listeners on page then we have super freezing on page. How to have one event listener on array of one and the same component?
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
Edited with code example. I use this component for displaying or hiding button if it not fit in window. I comment place where i create eventListeners
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
class BmResponsiveMenuButton extends PureComponent {
lastWidth = 0
resizeStep = 0
state = {
hidden: false
}
componentDidMount() {
//HERE ADDING EVENT LISTENERS (TOTALLY WE HAVE 15-20 LISTENERS ON PAGE)
window.addEventListener('resize', this.handleResize)
window.addEventListener('scroll', this.handleScroll, false)
this.anchorMenuButton = document.getElementById(this.props.moreMenuButtonId)
}
handleResize = () => {
this.handleHiddenOrNot()
}
componentDidUpdate() {
this.lastWidth = document.documentElement.clientWidth
}
handleHiddenOrNot = () => {
this.resizeStep = Math.abs(this.lastWidth - document.documentElement.clientWidth)
let boundingMenu = this.anchorMenuButton.getBoundingClientRect()
let boundingButton = this.anchorEl.getBoundingClientRect()
if (boundingButton.right > boundingMenu.left - 10) {
this.setState({
hidden: true
})
this.props.onHide(this.props.id)
} else {
this.setState({
hidden: false
})
this.props.onUnHide(this.props.id)
}
}
handleScroll = () => {
this.handleResize()
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize)
window.removeEventListener('scroll', this.handleScroll, false)
}
handleExited = () => {
let elem = this.anchorEl
elem.style.opacity = '0'
elem.style.visibility = 'hidden'
}
handleEnter = () => {
let elem = this.anchorEl
elem.style.opacity = '1'
elem.style.visibility = 'visible'
elem.style.position = 'sticky'
}
render() {
const {
title,
url,
classes,
target,
effects,
effectType,
index,
active,
currentModule,
module
} = this.props
const transitionProps = {
key: title,
in: !this.state.hidden,
enter: true,
exit: true,
timeout: !effects ?
0 : {
enter: this.resizeStep > 200 ? index * 100 : 300,
exit: 200
},
onEnter: () => this.handleEnter(),
onExited: () => this.handleExited()
}
let activeModule
if (module && currentModule === module) {
activeModule = true
} else if (active) {
activeModule = active
} else {
activeModule = url.includes(window.location.pathname + window.location.search + window.location.hash)
}
const ButtonComponent = ( <
Link to = {
url
}
target = {
target
}
innerRef = {
(node) => (this.anchorEl = node)
} >
<
Button className = {
classNames(classes.topNavigationButton, activeModule ? classes.selected : '')
} > {
title
} <
/Button> < /
Link >
)
switch (effectType) {
case 'slide':
return ( <
Slide direction = {
'left'
} { ...transitionProps
} > {
ButtonComponent
} <
/Slide>
)
case 'fade':
return <BmFade { ...transitionProps
} > {
ButtonComponent
} < /BmFade>
case 'grow':
return <BmGrow { ...transitionProps
} > {
ButtonComponent
} < /BmGrow>
default:
break
}
}
}
reactjs optimization addeventlistener event-listener
reactjs optimization addeventlistener event-listener
edited yesterday
asked yesterday
Marty
1579
1579
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
@AKX ready. added
– Marty
yesterday
1
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday
add a comment |
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
@AKX ready. added
– Marty
yesterday
1
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
@AKX ready. added
– Marty
yesterday
@AKX ready. added
– Marty
yesterday
1
1
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday
add a comment |
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53944434%2foptimize-array-of-component-which-have-window-event-listeners%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53944434%2foptimize-array-of-component-which-have-window-event-listeners%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Show us some code too. It's hard to tell what the actual case is now.
– AKX
yesterday
@AKX ready. added
– Marty
yesterday
1
Looks like you could just do with a bit of debouncing. davidwalsh.name/javascript-debounce-function
– AKX
yesterday