0

In here state(menuAction) is defined in Context.js file. Now I want to toggle class onClick(id="nav-icon1") so need to access that state in Navbar.js.

It gives error

TypeError: Cannot read property 'state' of undefined

Any help or suggestion appreciated.

image

Context.js

import React, { Component } from 'react'
import { LinkData } from './LinkData'

const DataContext = React.createContext();

class DataProvider extends Component {
  state = {
    sidebarOpen: false,
    menuAction: false,
    links: LinkData,
  }

  handleSidebar = () => {
    this.setState({ sidebarOpen: !this.state.sidebarOpen })
    this.setState({ menuAction: !this.state.menuAction });
  }

  render() {
    return (
      <DataContext.Provider
        value={{
          ...this.state,
          handleSidebar: this.handleSidebar
        }}
      >
        {this.props.children}
      </DataContext.Provider>
    )
  }
}
const DataConsumer = DataContext.Consumer;

export { DataProvider, DataConsumer }

Navbar.js

import React from 'react'
import styled from 'styled-components'
import { DataConsumer } from '../context/Context'
import { Link } from 'react-router-dom'

function Navbar() {
  const width = window.innerWidth


  return (
    <DataConsumer>
      {value => {
        const { handleSidebar } = value;
        return (
          <NavWrapper>
            <div className="nav-center">
              <img src={require('../logo.png')} alt="babyShark logo" className="logoContainerMini" />
              <div id="nav-icon1" onClick={handleSidebar} className={this.state.menuAction ? 'open' : null}>
                <span></span>
                <span></span>
                <span></span>
              </div>
            </div>
          </NavWrapper>
        );
      }}
    </DataConsumer>
  )
}

const NavWrapper = styled.nav`
  position: -webkit-sticky;
  position:sticky;
  top:0;
  width:100%;
  padding: 1rem 1.5rem;
  background: var(--mainGrey);
  border-bottom:3px solid var(--primaryColor);
  z-index:1;
.nav-center{
  display:flex;
  align-items:center;
  justify-content:space-between;
  max-width:1200px;
  margin:0 auto;
}
.logoContainerMini{
  max-height:50px;
}
#nav-icon1 {
      width: 40px;
      height: 30px;
      position: relative;
      -webkit-transform: rotate(0deg);
      -moz-transform: rotate(0deg);
      -o-transform: rotate(0deg);
      transform: rotate(0deg);
      -webkit-transition: .5s ease-in-out;
      -moz-transition: .5s ease-in-out;
      -o-transition: .5s ease-in-out;
      transition: .5s ease-in-out;
      cursor: pointer;
    }

    #nav-icon1 span {
      display: block;
      position: absolute;
      height: 6px;
      width: 100%;
      background: #195587;
      border-radius: 6px;
      opacity: 1;
      left: 0;
      -webkit-transform: rotate(0deg);
      -moz-transform: rotate(0deg);
      -o-transform: rotate(0deg);
      transform: rotate(0deg);
      -webkit-transition: .25s ease-in-out;
      -moz-transition: .25s ease-in-out;
      -o-transition: .25s ease-in-out;
      transition: .25s ease-in-out;
    }

    #nav-icon1 span:nth-child(1) {
      top: 0px;
    }

    #nav-icon1 span:nth-child(2) {
      top: 12px;
    }

    #nav-icon1 span:nth-child(3) {
      top: 24px;
    }

    #nav-icon1.open span:nth-child(1) {
      top: 18px;
      -webkit-transform: rotate(135deg);
      -moz-transform: rotate(135deg);
      -o-transform: rotate(135deg);
      transform: rotate(135deg);
    }

    #nav-icon1.open span:nth-child(2) {
      opacity: 0;
      left: -60px;
    }

    #nav-icon1.open span:nth-child(3) {
      top: 18px;
      -webkit-transform: rotate(-135deg);
      -moz-transform: rotate(-135deg);
      -o-transform: rotate(-135deg);
      transform: rotate(-135deg);
    }
`;

export default Navbar
3
  • Hi Pratik! I'm a little confused - does your Context.js file contain a Navbar (the one you've created)? How are the two files related? Commented Jan 21, 2020 at 13:53
  • 1
    instead of thinking to use class, use hooks. Simple prop will do the trick here. Commented Jan 21, 2020 at 14:04
  • Hello Ashley, here i am using context file for manage state, and i am using this state in Navbar.js file using context provider and consumer. Commented Jan 22, 2020 at 4:19

2 Answers 2

3

First you can not access this from a function component so maybe you can switch it to a class component or you should pass the needed values from parent component as a prop.

Also when you calculate next state from current state you should do

 this.setState(prevState => {
   return value: !prevState.value   
 });

its more safe.

Sign up to request clarification or add additional context in comments.

Comments

0

You are already passing menuAction from DataContext.Provider. So you can access that menuAction using DataConsumer value. So you don't need to use this.state in functional component. Snippet how to use it.

<DataConsumer>
  {value => {
    const { handleSidebar, menuAction } = value;
    return (
      ...your code here
    );
  }}
</DataConsumer>

Let me know if that helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.