Issue with custom header (scene.route is undefined) - javascript

I'm trying to have a custom header component in react native navigation 5, however I'm getting the following error:
TyperError: undefined is not an object (evaluating 'scene.route')
In my component:
export default CustomHeader2 = (props) =>
{
const {scene, previous, navigation } = props;
return (
<View style={{ width:'100%',height:50, flexDirection:'row', alignItems:'center', justifyContent:'space-between', backgroundColor:'white' }}>
<View style={{ height:50, flexDirection:'row', alignItems:'center' }}>
{previous ?
(<TouchableOpacity onPress={ ()=>{ navigation.goBack() } } style={{ width:50, height:'100%',flexDirection:'column',alignItems:'center', justifyContent:'center' }}>
<MaterialCommunityIcon name="arrow-left" style={{ color:'black', marginRight:0, fontSize:30 }}/>
</TouchableOpacity>)
:null
}
<Text style={{ fontSize:18, color:'rgb(68,68,68)',fontWeight:'bold' }}>{ scene.route.params.venue.name }</Text>
</View>
</View>
);
};
In my stack:
<Stack.Screen
name="VenueCard8"
component={VenueCard8}
headerShown={true}
options={({ route }) => ({ title: route.params.venue.name, header: () => (<CustomHeader2></CustomHeader2>) })}
/>

screen options
options={() => ({
header: (props) => (
<CustomHeader
{...props}
/>
)
})}
custom header:
const CustomHeader = (props) => {
console.log('props = ', props);
console.log('scene = ', props.scene);
return (
<View>
<Text>Hello</Text>
</View>
);
};

Try this way
export default CustomHeader2 = (props) => {
return (
.........
<Text style={.....}>{ props.route.params.venue.name }</Text>
......
);
};

Related

Send props to another screen

help, so lets say i got a bunch of data from an API (in Homescreen.js), which then i send to a component called "Artikel.js", how should i send the data in each of these articles to a screen called "DetailScreen.js". please someone help me, i'd appreciate it very very much, thanks in advance and sorry for bad english
const Homescreen = () => {
const [articles, setArticles] = useState([]);
const getArticles = () => {
axios
.get(
"https://newsapi.org/v2/top-headlines?country=us&apiKey=API_KEY",
{
params: {
category: "technology",
},
}
)
.then((response) => {
setArticles(response.data.articles);
})
.catch(function (error) {
console.log(error);
})
.then(function () {});
};
useEffect(() => {
getArticles();
}, []);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={articles}
renderItem={({ item }) => (
<Artikel
urlToImage={item.urlToImage}
title={item.title}
description={item.description}
author={item.author}
publishedAt={item.publishedAt}
sourceName={item.source.name}
url={item.url}
/>
)}
keyExtractor={(item) => item.title}
/>
</SafeAreaView>
);
};
export default Homescreen;
Artikel.js
const Artikel = (props) => {
const navigation = useNavigation();
const goToDetail = () => {
navigation.navigate("Detail", {judul: 'Asu'});
};
// const goToSource = () => {
// WebBrowser.openBrowserAsync(props.url);
// };
return (
<SafeAreaView style={styles.container}>
<Pressable onPress={goToDetail}>
<Image
style={styles.image}
on
source={{
uri: props.urlToImage,
}}
/>
</Pressable>
<View style={{ paddingHorizontal: 20, paddingBottom: 10 }}>
<Text style={styles.title}>{props.title}</Text>
<Text style={styles.deskripsi} numberOfLines={3}>
{props.description}
</Text>
<View style={styles.data}>
<Text style={styles.h2}>
source:<Text style={styles.sumber}> {props.sourceName}</Text>
</Text>
<Text style={styles.tanggal}>
{moment(props.publishedAt).format("MMM Do YY")}
</Text>
</View>
</View>
</SafeAreaView>
);
};
export default Artikel;
"DetailScreen.js"
const DetailScreen = (props) => {
return (
<SafeAreaView style={styles.container}>
<Header />
<View style={styles.image}>
<Image
source={{
uri: props.thumbnail,
}}
style={styles.image}
/>
</View>
<View style={styles.bodyartikel}>
<Text style={styles.judul}>PROPS TITLE</Text>
<Text style={styles.artikel}>
PROPS.ARTICLE
</Text>
<View style={styles.footer}>
<Text style={styles.h1}>
By: <Text style={styles.sumber}>Salman</Text>
</Text>
<Text>12 Okt 2020</Text>
</View>
</View>
</SafeAreaView>
);
};
export default DetailScreen;
i tried to make a list of the datas i need in Artikel.js and made it into a list, but it didnt work
So in your Article.js you have called an method to navigate to DetailScreen.js. You have can do like this.
In Article.js:
<Pressable onPress={() => goToDetail(props)}> // pass props as argument
<Image
style={styles.image}
source={{
uri: props.urlToImage,
}}
/>
</Pressable>
now in your goToDetail method:
// Catch passed arguments as props
const goToDetail = (props) => {
navigation.navigate('Details', {
title: props.title,
description: props.description,
})
// As for now just passing title and description from props
};
Now to access Passed data in Detail.js:
import { useRoute } from '#react-navigation/native';
const DetailScreen = () => {
let route = useRoute(); // using route hooks
let {title, data} = route.params
return (
<YourComponent/>
);
};
In this way you can pass data from one screen to another. For more detail you always can visit react native navigation docs: https://reactnavigation.org/docs/params

React Native: How to dispatch redux action from Custom Drawer

I have to dispatch logoutUser() action from CustomDrawerContentComponent. How can I do that?
I have a StackNavigator as well as Drawer Navigator in my app.
Also there is a CustomDrawerComponent to show the username of authenticated user as well as a sign up button in Drawer. Since it is outside the class, I'm unable to dispatch using props.
MainComponent.js
...other import statements
import {
fetchDishes,
fetchComments,
fetchPromos,
fetchLeaders,
logoutUser,
} from "../redux/ActionCreators";
const mapDispatchToProps = (dispatch) => ({
fetchDishes: () => dispatch(fetchDishes()),
fetchComments: () => dispatch(fetchComments()),
fetchPromos: () => dispatch(fetchPromos()),
fetchLeaders: () => dispatch(fetchLeaders()),
logoutUser: () => dispatch(logoutUser()),
});
const handleSignOut = () => {
//Here I have to dispatch logoutUser() but props.logoutUser() says undefined.
};
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<SafeAreaView
style={styles.container}
forceInset={{ top: "always", horizontal: "never" }}
>
<View style={styles.drawerHeader}>
<View style={{ flex: 1 }}>
<Image
source={require("./images/newlogo.png")}
style={styles.drawerImage}
/>
</View>
<View style={{ flex: 2 }}>
<Text style={styles.drawerHeaderText}>Ristorante Con Fusion</Text>
</View>
</View>
<View style={styles.displayName}>
<Avatar
title={props.screenProps.name.match(/\b(\w)/g).join("")}
rounded
>
{" "}
</Avatar>
<Text style={{ fontSize: 22, marginLeft: 5, color: "#fff" }}>
Hello, {props.screenProps.name}
</Text>
</View>
<DrawerItems {...props} />
<TouchableOpacity onPress={() => handleSignOut()}> //Here I am calling the function
<View style={{ flexDirection: "row", justifyContent: "center" }}>
<Icon name="sign-out" type="font-awesome" size={24} color="blue" />
<Text>Sign Out</Text>
</View>
</TouchableOpacity>
</SafeAreaView>
</ScrollView>
);
const MainNavigator = createDrawerNavigator(
{
Home: {
screen: HomeNavigator,
navigationOptions: {
title: "Home",
drawerLabel: "Home",
drawerIcon: ({ tintColor, focused }) => (
<Icon name="home" type="font-awesome" size={24} color={tintColor} />
),
},
},
...
...
...
{
initialRouteName: "Home",
drawerBackgroundColor: "#D1C4E9",
contentComponent: CustomDrawerContentComponent,
}
);
class Main extends Component {
componentDidMount() {
this.props.fetchDishes();
this.props.fetchComments();
this.props.fetchPromos();
this.props.fetchLeaders();
};
render() {
var displayName = this.props.user.user.displayName;
if (displayName == undefined) displayName = this.props.user.name;
return (
<Fragment>
<View
style={{
flex: 1,
paddingTop:
Platform.OS === "ios" ? 0 : Expo.Constants.statusBarHeight,
}}
>
<MainNavigator screenProps={{ name: displayName }} />
</View>
</Fragment>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Main);
You can use the following to import useDispatch
import { useDispatch } from 'react-redux'
and then call it in your handleSignOut like so:
const handleSignOut = () => {
const dispatch = useDispatch()
dispatch(logoutUser())
//Continue with normal logout and maybe other dispatches...
};
Your component is not connected to redux. You are not using mapDispatchToProps anywhere else besides declaring it. Please use connect() method https://react-redux.js.org/api/connect

Mapping over sent props using .map react native

i have two components one is called homeScreen the second is card i do fetch data in homeScreen i set it to state after i do send state through props to my card component .
Now my card components should generate 9 cards accoridng to the data i am sending through to it so i did map and i am getting this error
TypeError: Cannot read property '0' of undefined.
i tried to console.log props inside Card component and i could see data but for some reason the map isnt working
Card.js
const Card = props => {
Array.from({length: 9}).map((i, index) => {
console.log(props);
return (
<View style={{flex: 1}}>
<Text style={{flex: 1, backgroundColor: 'red'}}>
{props.title[1] ? `${props.title[index]}` : 'Loading'}
</Text>
<Text style={{flex: 1, backgroundColor: 'blue'}}>{props.rating[index]}</Text>
</View>
);
});
};
export default Card;
homeScreen.js
export default class HomeScreen extends React.Component {
state = {
title: [],
image: [],
rating: [],
isLoading: true,
};
componentDidMount() {
this.getData();
}
titleSend = () => {
if (!this.state.isLoading) {
{
Array.from({length: 9}).map((i, index) => {
return this.state.title[index];
});
}
}
};
imageSetter = () => {
Array.from({length: 9}).map((i, keys) => {
return (
<Image
key={keys}
style={{width: 50, height: 50, flex: 1}}
source={{uri: this.state.image[keys]}}
/>
);
});
};
getData = () => {
const requestUrls = Array.from({length: 9}).map(
(_, idx) => `http://api.tvmaze.com/shows/${idx + 1}`,
);
const handleResponse = data => {
const shows = data.map(show => show.data);
this.setState({
isLoading: false,
title: shows.map(show => show.name),
image: shows.map(show => show.image.medium),
rating: shows.map(show => show.rating.average),
});
// console.log(this.state);
};
const handleError = error => {
this.setState({
isLoading: false,
});
};
Promise.all(requestUrls.map(url => axios.get(url)))
.then(handleResponse)
.catch(handleError);
};
render() {
const {isLoading, title, image, rating} = this.state;
if (isLoading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ScrollView style={{flex: 1, backgroundColor: 'red'}}>
<Card title={this.state.title} />
</ScrollView>
<Text>here images</Text>
</View>
);
}
}
None of your functions/methods using Array.from are returning a value.
For example your Card component:
const Card = props => {
// note addition of `return` statement
return Array.from({length: 9}).map((i, index) => {
console.log(props);
return (
<View style={{flex: 1}}>
<Text style={{flex: 1, backgroundColor: 'red'}}>
{props.title[1] ? `${props.title[index]}` : 'Loading'}
</Text>
<Text style={{flex: 1, backgroundColor: 'blue'}}>{props.rating[index]}</Text>
</View>
);
});
};
export default Card;
The titleSend and imageSetter methods have a similar issue.
The index error is because you're not passing an rating prop to the Card component but you're accessing props.rating[0], props.rating[1], etc.
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ScrollView style={{flex: 1, backgroundColor: 'red'}}>
// missing `rating` prop
<Card title={this.state.title} />
</ScrollView>
<Text>here images</Text>
</View>
);

Cannot get child hook to receive state

I want to be able to pass the current user from my Comment component to my CommentList component
class Comment extends Component {
render() {
return(
<View>
<Header
rounded
style={{
backgroundColor: '#ffffff',
position: 'relative',
}}
>
<View style={{flexDirection: 'row', flexWrap: 'wrap', right: '43%', top: '50%'}}>
<Icon name='chevron-left' size={10} color='#006FFF' style={{top: '6%'}}/>
<NativeText
onPress={() => this.props.history.push('/')}
style ={{color: '#006FFF', fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
Back
</NativeText>
</View>
</Header>
<View
style={{paddingLeft: '2%', paddingTop: '2%'}}
>
<CommentList
options={this.props.location.state.comments}
currentUser={this.props.location.state.currentUser}
/>
</View>
</View>
)
}
}
export default withRouter(Comment)
const CommentList = (options, currentUser) => {
const [modalVisible, setModalVisible] = useState(false)
const [parentId, changeParentId] = useState('')
const [commentInput, changeComment] = useState('')
return (
<View>{console.log(currentUser)}
{options.options.map(option => (
<View>
<NativeText
style={{fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
{option.content}
</NativeText>
<Icon
name='reply'
size={12}
onPress={() => {
setModalVisible(true)
changeParentId(option._id)
}}
/>
{
<View
style={{left: '10%'}}
>
<CommentList
options={option.reply}
/>
</View>
}
</View>
))}
</View>
)
}
When I try to pass it through currentUser, it returns an empty object; options does show up in CommentList.
You are missing the object destructuring syntax for CommentList. It should be as follows:
const CommentList = ({ options, currentUser }) => {
// component content
}
The props you pass to functional component are consolidated into an object. So you need to destructure the values.
Or,
const CommentList = (props) => {
//props.options //props.currentUser
}

pass props to DrawerContent component

I want to pass props to Drawer so that i can display the name of user in the drawer component. If i export DrawerContent, i dont get the props like navigation etc.
routes.js
const navitems =[
{
name:'Home',
nav:'classesnew',
},
{
name:'Device',
nav:'start',
},
]
const mapDispatchToProps = (dispatch) => (
{
loadInitialData: () => dispatch(loadInitialData()),
}
);
const mapStateToProps = createStructuredSelector({
user: selectUser(), // fetch the name of user to show below
});
class DrawerContent extends React.Component{
constructor(props) {
super(props)
}
render(){
return (
<Image source={require('../images/logo.png')}
style={styles.container}>
<View style={{justifyContent: 'center',
alignItems: 'center',}}>
<Image style={styles.image} source={{uri: ''}}/>
<Text>{user.get('name')}</Text> {/* show username */}
</View>
<View>
{
navitems.map((l,i)=>{
return (
<TouchableOpacity
key={i}
style={{marginBottom:0.5}}
onPress={()=>{
this.props.navigation.navigate(l.nav)
}
}>
<View style={{flexDirection:'row', padding: 15, paddingLeft:0, backgroundColor:'#fff0', borderTopWidth:0.5, borderColor:'rgba(255,255,255, 0.5)', marginLeft: 20, marginRight:20}}>
<Icon name={l.icon} size={20} style={{paddingLeft:10, paddingRight: 20, height: 25, }} color="#ffffff" />
<Text style={{fontSize:16, fontWeight: 'bold',color:'#fff'}}>{l.name}</Text>
</View>
</TouchableOpacity>)
})
}
</View>
</Image>)
}
}
const DrawerRoutes = (
{
Main: { screen: App, title: 'Main' },
Device: { screen: Device, title: 'Device' },
})
const Drawer = DrawerNavigator(DrawerRoutes ,{
contentComponent:({navigation})=> <DrawerContent navigation={navigation} routes={DrawerRoutes} />,
});
Drawer.navigationOptions = {
contentOptions: {
activeBackgroundColor: '#ff5976',
style: {
backgroundColor: '#000000',
zIndex: 100,
paddingTop: 0
}
},
header: ({ state, setParams, navigate, dispatch }) => ({
visible: true,
tintColor: '#ffffff',
title: "LokaLocal",
style: {
backgroundColor: '#ff5976'
},
right: (
<TouchableOpacity
onPress={() => navigate('DrawerOpen')}
>
<Icon name="search" size={16} style={{ padding: 10, paddingRight: 20 }} color="#ffffff" />
</TouchableOpacity>
),
left: (
<TouchableOpacity
onPress={}
>
<Icon name="bars" size={16} style={{ padding: 10, paddingLeft: 20 }} color="#ffffff" />
</TouchableOpacity>
),
})
}
export const Routes = StackNavigator(
{
Login: { screen: Login },
Dashboard: {screen: Drawer},
},
index.js
import { Drawer } from './routes';
const App = () => (
<Provider store={store}>
<Drawer />
</Provider>
);
where should i use connect so i can use redux state as props to show username?
UPDATED
const mapDispatchToProps = (dispatch) => (
{
loadInitialData: () => dispatch(loadInitialData()),
}
);
const mapStateToProps = createStructuredSelector({
user: selectUser(),
});
class DrawerContent extends React.Component{
constructor(props) {
super(props)
}
componentDidMount() {
console.log('props are', this.props);
this.props.loadInitialData();
}
render() {
console.log('props', this.props);
return (
<View style={styles.container}>
<View>
<Image style={styles.image} source={require('../images/logo.png')}/>
<Text style={{ color: '#fff', fontSize: 11, paddingTop: 10, paddingBottom: 20 }}>username here</Text>
</View>
<View>
{
navitems.map((l,i)=>{
return (
<TouchableOpacity
key={i}
style={{marginBottom:0.5}}
onPress={()=>{
this.props.navigation.navigate(l.nav)
}
}>
<View style={{flexDirection:'row', padding: 15, paddingLeft:0, borderTopWidth:0.5, borderColor:'rgba(255,255,255, 0.5)',}}>
<Icon name={l.icon} size={20} style={{paddingLeft:10, paddingRight: 20, height: 25, }} color="#ffffff" />
<Text style={{fontSize:16, fontWeight: 'bold',color:'#fff'}}>{l.name}</Text>
</View>
</TouchableOpacity>)
})
}
</View>
</View>
)
}
}
const DrawerRoutes = (
{
Main: { screen: App, title: 'Main' },
Device: { screen: Device, title: 'Device' },
})
export const Drawer = DrawerNavigator(DrawerRoutes ,{
contentComponent:({navigation})=> <ContentDrawer navigation={navigation} routes={DrawerRoutes} />,
});
const ContentDrawer = connect(mapStateToProps, mapDispatchToProps)(DrawerContent);

Categories

Resources