My application runs properly. I use the EventListeners to swipe a side menu in and out. I pass the functions from the app component above as props to the child components. But when I run a snapshot test I get the following error:
TypeError: Cannot read property 'addEventListener' of null
21 | componentDidMount() { 22 | const aside = this.sideMenu.current; > 23 | aside.addEventListener("touchstart", this.props.onTouchStart); | ^ 24 | aside.addEventListener("touchmove", this.props.onTouchMove); 25 | aside.addEventListener("touchend", this.props.onTouchEnd); 26 | }
App.js (Parent component):
import React, { Component } from "react";
import styled from "styled-components";
import Header from "components/Header";
import Navbar from "components/Navbar";
import SideMenu from "components/SideMenu";
import MainContent from "components/Content";
const AppWrapper = styled.section`
height: 100vh;
width: 100vw;
display: grid;
grid-template-rows: 70px auto;
@media (max-width: 884px) {
grid-template-columns: 60vw auto;
}
@media (min-width: 885px) {
grid-template-columns: 200px auto;
}
`;
class App extends Component {
swipe = {
firstPositionX: null,
firstPositionY: null,
positionDifferenceX: null,
positionDifferenceY: null
};
constructor(props) {
super(props);
this.state = {
sideMenuDisplay: window.innerWidth >= 885 ? true : false
// movement: -60
};
}
componentDidMount() {
window.addEventListener("resize", this.updateSideMenuDisplay);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateSideMenuDisplay);
}
updateSideMenuDisplay = () => {
this.setState({ sideMenuDisplay: window.innerWidth >= 885 ? true : false });
};
toggleSideMenu = () => {
this.setState(prevState => ({
sideMenuDisplay: !prevState.sideMenuDisplay
}));
};
handleTouchStart = e => {
this.swipe.firstPositionX = e.touches[0].screenX;
this.swipe.firstPositionY = e.touches[0].screenY;
};
handleTouchMove = e => {
this.swipe.positionDifferenceX =
e.touches[0].screenX - this.swipe.firstPositionX;
this.swipe.positionDifferenceY =
e.touches[0].screenY - this.swipe.firstPositionY;
};
handleTouchEnd = () => {
if (Math.abs(this.swipe.positionDifferenceY) <= 150) {
this.setState(prevState => ({
sideMenuDisplay:
prevState.sideMenuDisplay === false
? this.swipe.positionDifferenceX > 50
: !(this.swipe.positionDifferenceX < -50)
}));
}
this.swipe.firstPositionX = null;
this.swipe.positionDifferenceX = null;
this.swipe.firstPositionY = null;
this.swipe.positionDifferenceY = null;
};
render() {
const sideMenuDisplay = this.state.sideMenuDisplay;
return (
<AppWrapper>
<Header display={sideMenuDisplay} />
<Navbar onClick={this.toggleSideMenu} display={sideMenuDisplay} />
<SideMenu
display={sideMenuDisplay}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
/>
<MainContent
display={sideMenuDisplay}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
/>
</AppWrapper>
);
}
}
export default App;
Sidemenu.js (Child component):
import React, { Component } from "react";
import SideMenuElement from "./SideMenuElement";
import MembersIcon from "./MembersIcon";
import DashboardIcon from "./DashboardIcon";
import {
SideMenuSection,
SideMenuItems,
SideMenuElementLogo,
AppMobileLogo
} from "./styles";
import logoIcon from "static/logo@3x.png";
class SideMenu extends Component {
constructor(props) {
super(props);
this.state = { selectedItem: "dashboard" };
// Create the ref
this.sideMenu = React.createRef();
}
componentDidMount() {
const aside = this.sideMenu.current;
aside.addEventListener("touchstart", this.props.onTouchStart);
aside.addEventListener("touchmove", this.props.onTouchMove);
aside.addEventListener("touchend", this.props.onTouchEnd);
}
componentWillUnmount() {
const aside = this.sideMenu.current;
aside.removeEventListener("touchstart", this.props.onTouchStart);
aside.removeEventListener("touchmove", this.props.onTouchMove);
aside.removeEventListener("touchend", this.props.onTouchEnd);
}
selectItem = item => {
this.setState({ selectedItem: item });
};
render() {
const selectedItem = this.state.selectedItem;
return (
<SideMenuSection display={`${this.props.display}`} ref={this.sideMenu}>
<SideMenuItems>
<SideMenuElementLogo>
<AppMobileLogo src={logoIcon} alt="App Logo" />
</SideMenuElementLogo>
<SideMenuElement
item="dashboard"
icon={DashboardIcon}
selected={selectedItem === "dashboard"}
onClick={this.selectItem}
>
Dashboard
</SideMenuElement>
<SideMenuElement
item="members"
icon={MembersIcon}
selected={selectedItem === "members"}
onClick={this.selectItem}
>
Members
</SideMenuElement>
</SideMenuItems>
</SideMenuSection>
);
}
}
export default SideMenu;
Aucun commentaire:
Enregistrer un commentaire