instance member is not accessible - react-native

How can I access class functions from inside stack navigator header? Is this possible?
What I'm trying to achieve is to call a function when I press the stack navigator header title.
class Dashboard extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: (
<View style={header.addressView}>
<Text
style={header.titleAddress}
onPress={() => {
this._show().bind(this);
}}>
/>
</View>
),
};
};
_show(){
this.setState({ visibleModal: 1 })
}
constructor(props) {
super(props);
this.state = {
visibleModal: null,
};
}
render() {
...........
}
}
export default Dashboard;

class Dashboard extends React.Component {
static navigationOptions = ({ navigation }) => {
const showParams = navigation.getParam("show",()=>{});
//Access the params like this.
return {
headerTitle: (
<View style={header.addressView}>
<Text
style={header.titleAddress}
onPress={showParams}>
/>
</View>
),
};
};
_show(){
this.setState({ visibleModal: 1 })
}
//Too add this.
componentDidMount(){
this.props.navigation.setParams({show:()=>this._show()});
}
constructor(props) {
super(props);
this.state = {
visibleModal: null,
};
}
render() {
...........
}
}
export default Dashboard;
This is how you access the variables or states inside a class and make it available for the static navigationOptions function.
Reference

Related

passing array state to another class react native

I am new to React Native. I am making a lunch picker app for practice, and I wonder how to pass array of state to another class.
What I want to do is: show all data of array in child screen, so users can check the data by clicking on a button.
However, it seems like my code returns null array instead of getting original array. All codes are in one file, App.js
Home screen
class HomeScreen extends React.Component {
//initial
constructor(props) {
super(props);
this.state = {
isReady: false,
myMenu: '????',
menutext: '',
randomArray: ['a', 'b', 'c'],
};
}
render() {
return (
<View style={[styles.mainContainer]}>
<DetailsScreen menuListAA={this.state.randomArray} />
<Button
label="Show all menu"
onPress={() => {
/* 1. Navigate to the menu page route with params */
this.props.navigation.navigate('Details', {
itemId: 0,
otherParam: 'Show all menu',
});
}}
/>
</View>
Details screen
class DetailsScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
static navigationOptions = {
title: 'All menu',
};
loadMenuList() {
const allMenuList = this.props.menuListAA;
return allMenuList.map((item, index) => <Text key={index}>{item}</Text>);
}
render() {
return (
<ScrollView>
<View style={styles.row}>{this.props.menuListAA}</View>
<Button
label="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</ScrollView>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
Let me know if you need more information.
Please replace your code with one below :
Home screen
class HomeScreen extends React.Component {
//initial
constructor(props) {
super(props);
this.state = {
isReady: false,
myMenu: '????',
menutext: '',
randomArray: ['a', 'b', 'c'],
};
}
render() {
return (
<View style={[styles.mainContainer]}>
<DetailsScreen menuListAA={this.state.randomArray} />
<Button
label="Show all menu"
onPress={() => {
/* 1. Navigate to the menu page route with params */
this.props.navigation.navigate('Details', {
itemId: 0,
otherParam: 'Show all menu',
});
}}
/>
</View>
Doubts Detail : replace View with Text component
class DetailsScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
static navigationOptions = {
title: 'All menu',
};
loadMenuList() {
const allMenuList = this.props.menuListAA;
return allMenuList.map((item, index) => <Text key={index}>{item}</Text>);
}
render() {
return (
<ScrollView>
//change View with Text as view cannot render characters and error says the same
<Text style={styles.row}>{this.props.menuListAA}</Text>
<Button
label="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</ScrollView>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
you can pass data from parent to child by set props for child component like this: <Child data={this.state.yourData} /> //the props name is data,
then in child component in componentWillMount() you can access it:
ComponentWillMount(){
this.setState({childData: this.props.data}) // childData is an state of child component,rename it to your own`
}
in some case data maybe changed so we must to check this in componentDidUpdate() :
componentDidUpdate(){
if(this.props.data != this.state.childData){ //it is necessary because this function called many time's
this.setState({childData: this.props.data})
}
if you was in parent & want to give any data from child you must pass a function that returned data as like below:
<Child getData={(value)=> console.log(value)} />
then in your child you can do this:
this.props.getData(anyDataYouWantGetInParent)
hope this answer will be helpful,let me know any question
good luck.

Conditional Screen Rendering - How to hide origin screen tabBar and Header

What i'm trying to achieve from the Orders Screen is: If the user is not logged in he is directed to another screen. Which is also part of the stack. The transition is well but the header of origin screen (which in this case is orders.js) doesnt change
Orders.js
class Orders extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerTitle: <TextHeader title={I18n.t('tabsLang.orders')} />,
headerTitleStyle: header.title,
headerLeft: <View />,
headerRight: <View />,
};
};
constructor(props) {
super(props);
this.state = {
orders: true,
isLoggedIn: false,
};
}
render() {
if (this.state.isLoggedIn) {
if (!this.state.orders) {
//Orders
return (
<View style={styles.container}>
<OrderItem />
</View>
);
} else {
//No Orders Screen
return <NoOrders />;
}
} else {
return <UserSplash/>;
}
}
}
export default Orders;
UserSplash.js
class Login extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
header: null,
};
};
render() {...
}
}
There are two things I need to point out.
1. Double Header confusion
<Order>
Static navigationOptions = {
headerTitle: Something
}
render(){
if(state.isLoggedIn){
<View>
... Show orders or not
</View>
} else {
<UserSplash>
Static navigationOptions = {
header: null
}
</UserSplash>
}
}
</Order>
if you look at this, when you disable the header of the UserSplash, you are literally disabling the doubleheaders last one. If you don't disable it, you will see 2 headers on top of the view.
2. NavigationOptions
When you are setting the
navigationOptions
you are declaring it as Static if you are realized that. So it is not possible to change the parameters. I suggest you separate the UserSplash from the Order.js and just Navigate with your navigation.
Hope it helps. Good luck!

Update value in StackNavigation custom header

I defined a custom view as a component for headerRight property in navigationOptions as bellow:
static navigationOptions = ({ navigation }) => {
return {
headerRight: navigation.getParam('headerRight', null),
};
};
and then in componentDidMount:
this.props.navigation.setParams({
headerRight: (<MessageDetailsHeader {...this.props}
title = {this.state.headerTitle}
subTitle = {this.state.headerSubTitle}
online = {this.state.online}
/>)
})
also i defined some state for updating values:
constructor(props) {
super(props);
this.state = {
headerTitle: null,
headerSubTitle: null,
headerOnline: false
};
}
Custom header view component defined as bellow:
export default class MessageDetailsHeader extends React.Component {
constructor(props) {
super(props);
this.state = {
title: this.props.title,
subTitle: this.props.subTitle,
online: this.props.online
};
}
componentWillReceiveProps(nextProps) {
this.setState({
title: nextProps.title,
subTitle: nextProps.subTitle,
online: nextProps.online,
})
}
render() {
return (
<View style={styles.headerContainer}>
<View style={styles.headerDetailsContainer}>
<Text style={styles.headerTitle}>{this.state.title}</Text>
<Text style={styles.headerSubTitle}>{this.state.subTitle}</Text>
</View>
<Avatar small rounded source={require('../images/no-profile.png')} activeOpacity={0.7} avatarStyle={this.state.online? styles.avatarOnline: styles.avatarOffline}/>
</View>
);
}
}
I need to call setState in screen and then update Custom View in navigation header, is this a right way?
Thanks in advance
Solved!
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
headerRight: <MessageDetailsHeader
title={params.headerTitle}
subTitle={params.headerSubTitle}
online={params.headerOnline}
/>
};
};
and then called bellow code to set new value, easily!
this.props.navigation.setParams({
headerSubTitle: 'online',
});

passing extraData to FlatList isn't working

I followed https://facebook.github.io/react-native/releases/next/docs/flatlist.html to make a FlatList and also passed this.state to extraData but still, once I delete an item, the item is still shown. I have also logged this.state to make sure the item is deleted and it indeed did. My code is below:
class DescriptionItem extends React.PureComponent {
render() {
return (
<TouchableOpacity
style={this.props.containerStyle}
onPress={(event) => {this.props.onPress(this.props.value)}}>
<Text style={this.props.style}>{this.props.value}</Text>
</TouchableOpacity>
)
}
}
export default class CardWorkDescriptionsList extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
refreshing: false,
};
}
_notifyItemSelected(text) {
if(this.props.onItemSelected) {
this.props.onItemSelected(text)
}
}
_onItemSelected = (selectedItem) => {
var array = this.state.data;
var index = array.indexOf(selectedItem)
array.splice(index, 1);
console.log(array)
this.setState({data: array });
console.log("yeah",this.state.data)
this._notifyItemSelected(selectedItem);
}
makeRemoteRequest = () => {
//TODO: fetch data
this.setState({data: descriptionsFake})
}
componentDidMount() {
this.makeRemoteRequest();
}
render() {
return (
<View style={styles.cardLight}>
<FlatList
data={this.state.data}
extraData={this.state}
renderItem={(item) => (
<DescriptionItem
containerStyle={styles.itemContainer}
style={styles.content}
value={item.item}
onPress={(selectedItem)=>this._onItemSelected(selectedItem)}/>
)}
keyExtractor={item => item.substring(0,20)}
/>
</View>
);
}
}
Try extending React.Component instead of PureComponent

How to dynamically change the header title text in a react native app?

I have been struggling with something that sounds simple. I have been trying to get button when onpressed is called. Have tried several combinators but nothing works. Any ideas?
export default class JobScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = ({navigation}) => ({
title: "Chat with"
});
onPressLearnMore(nav) {
// how do I update the title header
console.log("On Pressed" + nav)
}
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<Button
onPress={() => {this.onPressLearnMore(navigate)}}
title="Learn More"
color="#841584"
/>
</View>
);
}
}
Since the navigationOptions has access to the navigation object, you can set some param on the current screen with this.props.navigation.setParam({ title: ‘some title’ }) and then access it in navigationOptions like this
static navigationOptions = ({ navigation }) => {
const { state: { params = {} } } = navigation;
return {
title: params.title || ‘default title’,
};
}