Reputation: 160
I am creating an application with tabs. When clicking on any of the tabs you should update the class index-big
by modifying the state of this.state.addActiveTabs
but this does not happen.
I get the impression that this.state.addActiveTabs
comes empty and that's why the class never changes, but I do not understand why.
Edit: I think the problem comes from that openTabs
is a function with a push that creates the elements and can not update the content of a push of a function.
openTabs
is called from the brother component of Tabs. It is called when clicking on a menu item. When it is called is when it creates a tab and at the same time a div/iframe
The problem is that the .push
creates the html and after creating it within a function I am not able to access it. How could I do it? I need to change only one class, not to update the whole element or anything.
class App extends Component {
constructor(props, context){
super(props, context);
["openTabs", "removeTab", "activeTabs",].forEach((method) => {
this[method] = this[method].bind(this);
});
this.displayData = [];
this.state = {
navigation: {
menu: [],
},
tabs:{
tabsLi: [],
},
divIframe:{
tabsDivIframe: [],
},
tabsiframe: '',
showtabs: true,
showdata: this.displayData,
postVal: "",
addActiveTabs: "",
};
}
openTabs(e, url, iframe, trdtitle){
//Evitar apertura automatica href
e.preventDefault();
//Cambiar la primera letra a mayuscula y las demas a minusculas
function firstUppercase(string){
return string.charAt(0).toUpperCase() + string.slice(1);
}
trdtitle = firstUppercase(trdtitle.toLowerCase());
url = url.toLowerCase();
//Cambiar el estado
this.setState({
showtabs: false,
})
//Creacion de las tabs + mostrar componentes
if (this.state.tabs.tabsLi.includes(trdtitle) === false){
if(iframe === 'si'){
console.log(this.state.addActiveTabs);
this.displayData.push(<div key={trdtitle.replace(/ /g, "")} id={"myTab"+trdtitle.replace(/ /g, "")} className={this.state.addIndexTabs === trdtitle ? ' index-big' : ''}><iframe title={"iframe"+trdtitle} className="iframetab" src={url}></iframe></div>);
}
else{
this.displayData.push(<div key={trdtitle.replace(/ /g, "")} id={"myTab"+trdtitle.replace(/ /g, "")} className={this.state.addIndexTabs === trdtitle ? ' index-big' : ''}><div className="iframetab">{url}</div></div>);
}
this.setState({
tabs: { tabsLi:[...new Set(this.state.tabs.tabsLi),trdtitle].filter(function(el) { return el; })},
showdata : this.displayData,
postVal : trdtitle,
})
}
}
activeTabs(value){
this.setState({
addActiveTabs: value,
})
return () => this.setState({
addIndexTabs: value,
});
}
render(){
return (
<>
<Tabs
navigation={this.state.navigation}
textvalue={this.state.textvalue}
showtabs={this.state.showtabs}
tabs={this.state.tabs}
tabsLi={this.state.tabs.tabsLi}
divIframe={this.state.divIframe}
tabsDivIframe={this.state.divIframe.tabsDivIframe}
tabsiframe={this.state.tabsiframe}
showdata={this.state.showdata}
addActiveTabs={this.state.addActiveTabs}
openTabs={this.openTabs}
removeTab={this.removeTab}
displayData={this.displayData}
activeTabs={this.activeTabs}
/>
</>
)
}
}
class Tabs extends Component {
constructor(props, context){
super(props, context);
["showCloseTabs", "hideCloseTabs"].forEach((method) => {
this[method] = this[method].bind(this);
});
this.state = {
closeTabs: false,
};
}
showCloseTabs(index, value){
this.setState({
closeTabs : true,
valueTabs: value,
})
}
hideCloseTabs(){
this.setState({
closeTabs: false,
})
}
render(){
return(
<div id="content-tabs" className="tabs">
{( this.props.showtabs)
? (
<>
<div className="waiting-leads">
<p>Parece que todavía no hay ningún lead...</p>
<h3>¡Ánimo, ya llega!</h3>
<img src={imgDinosaurio} alt="Dinosaurio"></img>
</div>
</>
) : (
<>
<ul id="resizable" className="content" >
<LiTabs
tabsLi={this.props.tabs.tabsLi}
closeTabs={this.state.closeTabs}
addActiveTabs={this.props.addActiveTabs}
valueTabs={this.state.valueTabs}
removeTab={this.props.removeTab}
activeTabs={this.props.activeTabs}
showCloseTabs={this.showCloseTabs}
hideCloseTabs={this.hideCloseTabs}
/>
</ul>
<DivAndIframe
tabsDivIframe={this.props.divIframe.tabsDivIframe}
tabsiframe={this.props.tabsiframe}
displayData={this.props.displayData}
/>
</>
)}
</div>
);
}
}
class LiTabs extends Component{
render(){
return(
<>
{this.props.tabsLi.map((value, index) =>
<li key={index}
onClick={(e) => this.props.activeTabs(value)}
onMouseEnter={(e) => this.props.showCloseTabs(e, value)}
onMouseLeave={(e) => this.props.hideCloseTabs(e, value)}
className={this.props.addActiveTabs === value ? ' active' : ''}>
<span>{value}</span>
<div onClick={this.props.removeTab.bind(this, value, index)} >
{this.props.closeTabs && this.props.valueTabs === value &&(
<Icon icon="cerrar" className='ico-cerrar'/>
)}
</div>
</li>
)}
</>
);
}
}
class DivAndIframe extends Component{
render(){
return(
<div className="content-modules">
{this.props.displayData}
</div>
);
}
}
Upvotes: 1
Views: 100
Reputation: 5437
Make a use of closure to hold the value of your tab value in the onClick
handler like below:
activeTabs(value){
return () => this.setState({
addActiveTabs: value,
});
}
and then on your onClick, change it to below:
<li key={index}
onClick={(e) => this.props.activeTabs(value)}
className={this.props.addActiveTabs === value ? ' active' : ''}>
<span>{value}</span>
</li>
Upvotes: 3