program_bumble_bee
program_bumble_bee

Reputation: 305

Passing active tab event to parent and sibling component

I have Tab navigator that handles data changing of itself and other two sibling component.

Main parent Component that does data fetching and manipulation based on three sentiments: positive, negative and neutral as request body parameter in http post request.

Second parent component that stores all positive data, negative data and neutral data from main parent component.

Then three Child Components: Table one and Tab Navigation.

The Tab navigation has three three tabs namely: Positive, Negative and Neutral.

As soon as the page renders on first load, by default (without clicking positive tab button), it fetches positive data and displays it in all three child components. Then on clicking on Negative tab, it should display negative data in all three child components i.e. Table one and under negative tab of tab navigation. Same thing follows for Neutral Tab.

In short, Tab navigation handles data rendering of it's self and sibling components based on its active state and getting that data from parent component.

I tried passing the active event from tab navigation to its upper container but it doesn't seem to work fine.

Tab.js

import React, { Component } from 'react';


export default class Tab extends Component 
{
    constructor(props) 
    {
        super(props);
        this.state = 
        {   
            active: 'positive',

        }
    }



    toggle = (event) => 
    { 

        this.setState({
          active: event
        })

        this.props.sendEvent(this.state.active);
 }

    get_tab_content =()=>
    {
        switch(this.state.active)
        { 
            case 'positive':
                return <div><SomeDataComponent1 positiveprops={} /></div>; 
            case 'negative':
                return <div><SomeDataComponent2  negativeprops={}/></div>;
            case 'neutral':
                return <div><SomeDataComponent3  neutralprops={} /></div>;
            default : 
        }
    }

  render() {

    const tabStyles = {
        display: 'flex',
        justifyContent: 'center',
        listStyleType: 'none', 
        cursor: 'pointer', 
        width: '100px',
        padding: 5,
        margin: 4,
        fontSize: 20,
        color: 'green'
      }


    const tabStyles2 = {
        display: 'flex',
        justifyContent: 'center',
        listStyleType: 'none', 
        cursor: 'pointer', 
        width: '100px',
        padding: 5,
        margin: 4,
        fontSize: 20,
        color: 'red'
      }


      const tabStyles3 = {
        display: 'flex',
        justifyContent: 'center',
        listStyleType: 'none', 
        cursor: 'pointer', 
        width: '100px',
        padding: 5,
        margin: 4,
        fontSize: 20,
        color: 'yellow'
      }


    const linkStyles = {
      display: 'flex',
      justifyContent: 'center',
      color: '#000',
      listStyleType: 'none'
    }

    const divStyle = {
      border: '1px solid #34baa2',
        width: '450px'
    }

    const box = this.get_tab_content()

    return (
      <div style={divStyle} >
        <ul style={linkStyles}>
          <li style={tabStyles} onClick={function(){this.toggle('positive')}.bind(this)}>Positive</li>
          <li style={tabStyles2} onClick={function(){this.toggle('negative')}.bind(this)}>Negative</li>
          <li style={tabStyles3} onClick={function(){this.toggle('neutral')}.bind(this)}>Neutral</li>
        </ul>
        <div>
            {box}
        </div>
      </div>
    );
  }

 }

Second Parent Component.js

import React,{Component} from 'react';
import Tab from '../tab/tab';

import MentionTable from '../table/table';


class DataCharts extends Component{
constructor(props){
    super(props);

    this.state = {
        childEvent: ''
    }
}


getEvent = (childevent) => {
    this.setState({
        childEvent: childevent
    });

    console.log(this.state.childEvent)
}


    render(){
        const {positivetable,positivewords,  negativetable,  negativewords, neutraltable, neutralwords } = this.props;


        return(

                <div style={{display:'flex', flexDirection: 'row'}}>
                        <Table />

                        <Tab sendEvent={this.getEvent}/>
                </div> 

        )
    }
}


export default DataCharts;

Upvotes: 3

Views: 2542

Answers (2)

Dennis Vash
Dennis Vash

Reputation: 53884

The problem with your code is the next lines:

  toggle = event => {
    this.setState({
      active: event
    });

    this.props.sendEvent(this.state.active);
  };

setState is asynchronous, so you sending to sendEvent the not intended state.

  toggle = event => {
    this.setState(prevState => {
      console.log('prevState', prevState);
      console.log(event);
      this.props.sendEvent(event);
      return { active: event };
    });
  };

Edit Passing Props

Upvotes: 1

Abhisar Tripathi
Abhisar Tripathi

Reputation: 1659

I think calling the parent function in setState callback would work, for thet we need to do it like this in Tab.js

this.setState({
          active: event
        }, () => { this.props.sendEvent(this.state.active)})

also console.log(this.state.childEvent) should be also in callback too so that you get the state after it has been updated, we need to change DataCharts.js too

this.setState({
              childEvent: childevent
            }, () => { console.log(this.state.childEvent)})


 Working demo -: https://stackblitz.com/edit/react-zhbmad

Upvotes: 1

Related Questions