I am using FlatList
to display Image
and Text
side by side in a Component screen. I want to click on any row and open a new Component class[FoodItems] and passing just a simple string.
It says, "Cannot read properties of undefined (reading 'navigate')". I have installed all required packages.
npm install react-navigation
npm install @react-navigation/native
I don't know what this.props
here is? I am not sending props from previous screen. I just copy paste it from some post.
Restaurants.js:
import { View, FlatList, Text, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import withRouter from './withRouter';
class Restaurants extends Component {
render() {
if (!this.state.restaurantsSet) {
this.setState({ restaurantsSet: true });
this.settingRestaurants(this.props.location.state.station);
}
return (
<View>
<div className='header'></div>
<FlatList
ItemSeparatorComponent={this.FlatListItemSeparator}
ListHeaderComponent={this.FlatListHeader}
style={{ flex: 1 }}
data={this.state.restaurants}
renderItem={({ item }) =>
<TouchableOpacity
onPress={() =>
this.props.navigation.navigate(
'FoodItems',
{ message: 'my_message' }
)
}
>
<Row {...item} />
</TouchableOpacity>
}
/>
</View>
)
}
}
export default withRouter(Restaurants);
withRouter.js:
import { useLocation, useParams, useNavigation } from 'react-router-dom';
const withRouter = WrappedComponent => props => {
const location = useLocation();
const params = useParams();
const navigation = useNavigation();
return (
<WrappedComponent
{...{props, params}}
{...{ location, params,}}
{...{navigation, params}}
/>
);
};
export default withRouter;
The withRouter
HOC is implemented incorrectly. The useNavigation
hook is a RRDv6.4 Data router only hook. Emphasis mine.
This hook tells you everything you need to know about a page navigation to build pending navigation indicators and optimistic UI on data mutations. Things like:
- Global loading indicators
- Disabling forms while a mutation is happening
- Adding busy indicators to submit buttons
- Optimistically showing a new record while it's being created on the server
- Optimistically showing the new state of a record while it's being updated
Important
This feature only works if using a data router, see Picking a Router
import { useNavigation } from "react-router-dom"; function SomeComponent() { const navigation = useNavigation(); navigation.state; navigation.location; navigation.formData; navigation.formAction; navigation.formMethod; }
The useNavigation
hook isn't used to issue any imperative navigation actions. For this you should import and use the useNavigate
hook as this is the hook that returns the navigate
function.
import { useLocation, useParams, useNavigate } from 'react-router-dom';
const withRouter = WrappedComponent => props => {
const location = useLocation();
const params = useParams();
const navigate = useNavigate();
return (
<WrappedComponent
{...props}
{...{ location, params, navigate }}
/>
);
};
export default withRouter;
The in the React Class component access this.props.navigate
. Don't forget that data you want to pass in route state is passed in the option
object's state
property.
import { View, FlatList, Text, TouchableOpacity } from 'react-native';
import withRouter from './withRouter';
class Restaurants extends Component {
...
componentDidMount() {
if (!this.state.restaurantsSet) {
this.setState({ restaurantsSet: true });
this.settingRestaurants(this.props.location.state?.station);
}
}
...
render() {
return (
<View>
<div className='header'></div>
<FlatList
ItemSeparatorComponent={this.FlatListItemSeparator}
ListHeaderComponent={this.FlatListHeader}
style={{ flex: 1 }}
data={this.state.restaurants}
renderItem={({ item }) =>
<TouchableOpacity
onPress={() =>
this.props.navigate(
'FoodItems',
{ state: { message: 'my_message' }}
);
}
>
<Row {...item} />
</TouchableOpacity>
}
/>
</View>
)
}
}
export default withRouter(Restaurants);