简体   繁体   中英

Render a component within a component from onClick event in Reactjs

Here is a short demo of what I am trying to accomplish .

When "Tickers" is active in the menu, it should bring up the Tabs component. When other menu items are active, the Tabs component should not be rendered. I have a Content, SideMenu , and Tabs component. It seems to me that the best way to accomplish this would be to pass states around between components. So the button in the SideMenu component will trigger the Content component to render the Tabs component. How do I go about doing this?

Content.js

import React from 'react'
import { Grid, Image, Segment } from 'semantic-ui-react'
import '../index.css';

import Tabs from './content/Tabs';
import SideMenu from './content/SideMenu';

class Content extends React.Component{

  constructor(){
    super();
  }

  render(){

    return(
      <div>
        <Grid relaxed columns='equal' padded>
          <Grid.Column width={2} >
            <SideMenu />
          </Grid.Column>
          <Grid.Column width = {1}>
          </Grid.Column>
          <Grid.Column width={10}>
            <Tabs />
          </Grid.Column>
        </Grid>
      </div>
    )
  }
}

export default Content

SideMenu.js

import React, { Component } from 'react'
import { Menu } from 'semantic-ui-react'


export default class SideMenu extends Component {
  constructor(props){
    super(props);

    this.state = { activeItem: 'Tickers' };
  }


  handleItemClick = (e, { name }) => this.setState({ activeItem: name })

  render() {
    const { activeItem } = this.state

    return (
      <Menu pointing secondary vertical>
        <Menu.Item name='Tickers' active={activeItem === 'Tickers'} onClick={this.handleItemClick} />
        <Menu.Item name='All Time Highs' active={activeItem === 'All Time Highs'} onClick={this.handleItemClick} />
        <Menu.Item name='Article Sentiment' active={activeItem === 'Article Sentiment'} onClick={this.handleItemClick} />
      </Menu>
    )
  }
}

Tabs.js

import React from 'react'
import { Tab } from 'semantic-ui-react'

const panes = [
  { menuItem: 'Tab 1', render: () => <Tab.Pane attached={false}>Tab 1 Content</Tab.Pane> },
  { menuItem: 'Tab 2', render: () => <Tab.Pane attached={false}>Tab 2 Content</Tab.Pane> },
  { menuItem: 'Tab 3', render: () => <Tab.Pane attached={false}>Tab 3 Content</Tab.Pane> },
]

const Tabs = () => (
  <Tab menu={{ secondary: true }} panes={panes} />
)

export default Tabs

i have solution for that, you can move the activeItem and handleItemClick to Content.js and then passing to side menu component, so we can make conditional rendering in Content.js

Content.Js

import React from 'react'
import { Grid, Image, Segment } from 'semantic-ui-react'

import Tabs from './content/Tabs';
import SideMenu from './content/SideMenu';

class Content extends React.Component{
  constructor(){
    super();
    this.state = { activeItem: 'Tickers' }; //move state from SideMenu.js
  }
  handleItemClick = (e, { name }) => this.setState({ activeItem: name }) //move function onClick from SideMenu.js
  render(){
    const { activeItem } = this.state //call the state
    return(
      <div>
        <Grid relaxed columns='equal' padded>
          <Grid.Column width={2} >
            <SideMenu handleItemClick={this.handleItemClick} activeItem={activeItem} /> {/* passing the handleItemClick and activeItem */}
          </Grid.Column>
          <Grid.Column width = {1}>
          </Grid.Column>
          <Grid.Column width={10}>
            { this.state.activeItem === 'Tickers' && //this is for conditional render Tabs.js
              <Tabs />
            }
          </Grid.Column>
        </Grid>
      </div>
    )
  }
}

and then in your SideMenu.js access the data from Content.js using this.props

SideMenu.js

import React, { Component } from 'react'
import { Menu } from 'semantic-ui-react'


export default class SideMenu extends Component {
  constructor(props){
    super(props); //move state to Content.js
  }
  // move function to Content.js
  render() {
    //move state to Content.js
    return (
      <Menu pointing secondary vertical>
        {/* access activeItem and handleItemClick using this.props */}
        <Menu.Item name='Tickers' active={this.props.activeItem === 'Tickers'} onClick={this.props.handleItemClick} />
        <Menu.Item name='All Time Highs' active={this.props.activeItem === 'All Time Highs'} onClick={this.props.handleItemClick} />
        <Menu.Item name='Article Sentiment' active={this.props.activeItem === 'Article Sentiment'} onClick={this.props.handleItemClick} />
      </Menu>
    )
  }
}

I hope that can help you, please notice me if you have an error, thanks :)

You should have logic for conditional rendering where on click you set some flag. Based on the flag you can display nested component like mentioned here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM