Nativebase Tabs not changing content when changing page value - reactjs

I am having problems with navigating to a tab from another screen. When I am on the page clicking the tabs, the content switches fine, but when I try to set the active tab from another component before navigating to that screen, I am having issues with going to the specified tab.
I've tried passing parameters through the navigation to the parent screen like this: this.props.navigation.navigate('Menu', {goToOrderDetails: true}) and then inside the Menu screen, I made a componentFocused function where every time the page is in focus, I am checking if that goToOrderDetails parameter is true, and if it is, I am manually setting the state variable that is being used to set the active tab. This, however, is not working and just returns directly to the default tab (0), however, the styling color indicators are on the correct tab, but the content is that of the first tab.
This is how I am currently trying to do it:
Here is the Menu screen:
import React, {Component} from 'react';
import {observer} from "mobx-react";
import {ScrollView} from 'react-native';
import {Container, Tab, Tabs, ScrollableTab} from 'native-base';
import OrderHistory from './OrderHistory';
import Favorites from '../components/Favorites';
import Heading from '../components/Heading';
import store from '../store/store';
import i18n from 'i18n-js';
class Menu extends Component {
constructor() {
super();
this.subs;
this.state = {
activeTab: 0,
initialPage: 0
};
}
getTab() {
if(this.props.navigation.state.params){
if(this.props.navigation.state.params.page == 'orderhistory') {
return 2;
}if(this.props.page == 'favorites'){
return 1;
}else{
return 0;
}
} else {
if (this.props.navigation.getParam('orderHistory') || store.toOrderHistory == true) {
return 2;
} else if (this.props.navigation.getParam('favorites')) {
return 1;
}
store.toOrderHistory.set(false);
}
}
componentDidMount() {
this._componentFocused();
this._sub = this.props.navigation.addListener(
'didFocus',
this._componentFocused
);
}
_componentFocused = () => {
store.updateActiveTab(this.getTab());
}
updateTab(tab) {
store.updateActiveTab(tab.i);
}
render() {
return (
<Container>
<Heading title={'Menu'} />
<Tabs onChangeTab={(tab) => {this.updateTab.bind(this, tab)}}
page={store.activeTab.get()}
renderTabBar={()=> <ScrollableTab />}>
<Tab heading={i18n.t('menu.all_tab')}>
<ScrollView>
{this.displayMenu()}
</ScrollView>
</Tab>
<Tab heading={i18n.t('menu.fav_tab')}>
<Favorites></Favorites>
</Tab>
<Tab heading={i18n.t('menu.recent_tab')}>
<OrderHistory></OrderHistory>
</Tab>
</Tabs>
</Container>
)
};
}
export default observer(Menu);
And I am trying to send the navigation parameter from the order details screen to this screen like this: this.props.navigation.navigate('Menu',{goToOrderDetails: true}) and when that parameter is true, I am updating the store activeTab value like this: store.updateActiveTab.set(2).
The strangest part is that if I console.log the tab value, it is 2! Which is the correct one I need it to be on! And as I mentioned earlier, the color of the title is also the active color! It is just the content and the color underline that are not on that tab.
Is it possible that it is necessary to refresh the entire tabs component so that I can change the active tab from another screen? I am not sure why this behavior is occurring and could use some help!
Here is a screenshot of what happens after I have manually changed the active tab from the order details component!

I am also using same tab and implement as below:
<Tabs ref={(c) => { this.bottomTabRef = c; }} initialPage={0} page={pageNum} onChangeTab={({ from, i }) => { this.setState({ pageNum: i }); this.bottomTabRef.goToPage(0); }}>
<Tab heading="tab1">
<Text> Tab1 </Text>
</Tab>
<Tab heading="tab2">
<Text> Tab2 </Text>
</Tab>
</Tabs>

Related

How can I re-render(refresh) bottom tab bar in react native?

I am struggling with the
import { create Bottom Tab Navigator } from '#react-navigation/bottom-tabs';
I want re-render bottom tab after removing cart Items from cart component by dispatch action and my focused tab is cart tab,
and i am also used a custom components for getting cart Count from state below i am sharing the code of bottom tab icon.
export class Cart Badge Icon extends Component {
constructor(props){
super(props);
}
render() {
return (
<>
<Image source={this.props.is-focused ? IMP_CONT.CART_ACTIVE :
MG_CONT.CART_INACTIVE} style={{ width: scale(25), height: scale(22) }} />
{this.props.counterproductive ?
(<View
>
<Text>{this.props.cart Count}
</Text>
</View>
) : null}
</>
)
}
}
cont map State To Props = (state) => ({
cart Has Product Flag: state.cart.cart Has Product,
cart Count: state.cart.cart Count,
})
export default connect(map State To Props)(Cart Badge Icon)
and i have import this component in my bottom Tab like this <Cart Badge Icon/>
after one day's i fond the solution,
i dispatch a action for receiving cartCount and i already get cartCout in CartBadgeIcon component.

React Boostrap Tabs not showing tab content

I've seen this question asked before but have not seen an answer. I have two tabs for now but neither tab shows any content. I've pared it all back to its most basic functioning. I'm not trying to display a component in the tab; just an h1 for now. Based on a comment from here I added a link to the header of my index.html and it is still a stubborn no-show. Here's what I'm working with:
import React, { Component, useState } from 'react';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
export class GameHome extends Component {
static displayName = GameHome.name;
constructor(props) {
super(props);
this.state = {
};
this.componentDidMount = this.componentDidMount.bind(this);
}
componentDidMount() {
}
render = () => {
return (
<Tabs defaultActiveKey="tab1" id="uncontrolledTabs">
<Tab eventKey="tab1" title="Tab 1">
<h1>Tab 1</h1>
</Tab>
<Tab eventKey="tab2" title="Tab 2">
<h1>Tab 2</h1>
</Tab>
</Tabs>
);
}
}

State is not getting changed after simulating click event

I am trying to create test cases for my application, providing source below:
import React, {Component} from 'react';
import {Tabs, Tab} from 'react-bootstrap';
import ManageUsers from './ManageUsers.jsx';
import ManageRoles from './ManageRoles.jsx';
import ManageUserGroups from './ManageUserGroups.jsx';
export default class UserManagement extends Component {
constructor(props) {
super(props);
this.handleSelect = this.handleSelect.bind(this);
this.state = {
selectedTab: 1
}
}
handleSelect(key){
this.setState({
selectedTab: key
});
}
render() {
return (
<div className="container listView">
<Tabs activeKey={this.state.selectedTab} onSelect={this.handleSelect} className="customNavTabsHorizontal" id="navUserMgmt">
<Tab eventKey={1} title={this.state.multiLangMsgs.MANAGE_USERS}>
<ManageUsers isSelected={this.state.selectedTab === 1 ? true : false} ></ManageUsers>
</Tab>
<Tab eventKey={2} title={this.state.multiLangMsgs.MANAGE_ROLES_PERMISSIONS}>
<ManageRoles isSelected={this.state.selectedTab === 2 ? true : false} ></ManageRoles>
</Tab>
<Tab eventKey={3} title={this.state.multiLangMsgs.MANAGE_USER_GROUPS}>
<ManageUserGroups isSelected={this.state.selectedTab === 3 ? true : false}></ManageUserGroups>
</Tab>
</Tabs>
</div>
);
}
}
and the test case is like this
import React from 'react';
import {shallow} from 'enzyme';
import UserManagement from './UserManagement.jsx';
describe('<UserManagement />', () => {
it('should handle selected tab state changes', () => {
const userMgmt = shallow(<UserManagement />);
const secondTab = userMgmt.find('Tab').at(0);
secondTab.simulate('click');
expect(userMgmt.state().selectedTab).toEqual(2);
});
});
When I run the npm test it always gets fail saying that expected is 2 but actual is 1. It seems it's not setting the state value. Can any one please help me out with this.
When you use shallow rendering, it renders only elements exactly from one render function you test. It doesn't know how to handle click on Tab.
To simultate your case, you have 2 option:
Render also children nodes using mount rendering, and simulate click on DOM node.
Call onSelect or simultate select on Tabs element.

How to make `Menu` in material-ui don't reset scroll position after rerendering?

<Menu onChange={this.props.onChange}>
{ items }
</Menu>
I have a Menu with a lot of items like this, every time when I update the state, the scroll position of the menu is resetted.
I tested with ul
<ul>
{ item }
</ul>
it works, the position isn't resetted after rerendering.
here is the source code of material-ui/Menu.js, as I'm new to js, I can't find anything about why the scroll position is resetted.
here is the code, if you scroll to the bottom, and then click the 23 item, the scroll position will be resetted.
The problem was with the event handler, you need to add preventDefault() this stops the default action.
import React from "react";
import ReactDOM from "react-dom";
import { MuiThemeProvider, Menu, MenuItem, MenuList } from "material-ui";
export default class Hello extends React.Component {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
event.preventDefault();
console.log("Hello");
}
render() {
const array = Array.from({ length: 25 }, i => 1);
const items = Object.keys(array).map(key => {
return <MenuItem key={key} value={key} primaryText={key} />;
});
return (
<MuiThemeProvider>
<Menu
onChange={this.handleChange}
>
{items}
</Menu>
</MuiThemeProvider>
);
}
}
finally, I use List instead of Menu to solve this problem.

React Native : Regarding State and Callback handlers

So I am still learning React Native and I am trying to build a very simple app to understand state, events in React Native.
Here in this app I display a button titled "first" as soon as the app is rendered on the screen.
Upon clicking that button a modal is displayed. This modal contains a button titled "second".
The objective is to hide the modal upon "onPress" of the "second" button.
Thsi is my code.
import React from 'react';
import { StyleSheet, Text, View, Button, Modal } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.showModal = this.showModal.bind(this);
}
state = {
modalVisible: false,
}
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisbile: false});
}
showModal() {
console.log("BtnPress1 pressed");
this.setState({modalVisible: true});
}
render() {
return (
<View style={styles.container}>
<Button title="first"
onPress={this.showModal}
disabled={this.state.modalVisible} />
<Modal
animationType= "slide"
transparent= {false}
visible={this.state.modalVisible}
>
<Button
title="second"
onPress={this.hideModal}
disabled={!this.state.modalVisible}
/>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
What Happens
a) There are no errors.
b) The app is rendered successfully and display the button "first".
c) When the "first" button is clicked, the second button("second") contained in the modal is rendered as expected.
d) But when the "second" button is clicked the "first" button is not rendered.
My understanding is that upon "onPress" event on "second" button the below callback is invoked which changes the state.
onPress={this.hideModal}
After changing that state (which would now be modalVisible = false) the button titled "first" will be rendered. But this is not happening.
Can some one tell em what I am doing wrong ?
In your code, you misspelled visible, if you correct the spelling, it looks like it will work
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisible: false}); /*you had modalVisbile*/
}

Resources