StackNavigator 的子组件在其父组件外部调用时呈现两次
StackNavigator's child component rendered twice when called outside of its parent
我使用 React Navigation 在我的 React Native 应用程序的屏幕之间导航。我的屏幕结构是:
- DrawerNavigator
- HomeScreen
- MoviesStackNavigator
- MoviesListScreen
- MovieDetailsScreen
- DiscoverScreen
现在我想导航并将一些参数从 DiscoverScreen 传递到 MoviesListScreen。
这是我的代码:
DiscoverScreen.js
onSearchConfirm() {
this.setState({searching: true})
var params = {
sort_by: this.state.sortBy,
year: this.state.releaseYear,
with_genres: this.state.genreIds.join(',')
};
const _this = this;
return fetch(Configuration.TMDB_BASE_URL
.concat('/discover/movie?')
.concat(Utility.stringFromQueryParams({...params, api_key: Configuration.TMDB_API_KEY})))
.then(response => response.json())
.then(jsonResponse => {
_this.setState({searching: false});
const navigateAction = NavigationActions.navigate({
routeName: 'MoviesList',
params: {data: jsonResponse}
})
_this.props.navigation.dispatch(navigateAction)
})
.catch(err => console.error(err.toString()))
}
抽屉导航器:
export default MenuNavScreen = DrawerNavigator(
{
Home: {
screen: HomeScreen
},
Movies: {
screen: MoviesStackNavigator
},
DiscoverMovies: {
screen: DiscoverScreen
},
About: {
screen: AboutScreen
},
},
{
initialRouteName: 'Home'
})
电影堆栈导航器:
export default MoviesStackNavigator = StackNavigator({
MoviesList: {
screen: MoviesListScreen
},
MovieDetails: {
screen: MovieDetailsScreen
},
});
最后,我检查参数的代码
电影列表屏幕:
//...
componentWillMount() { //THIS IS CALLED TWICE
if(!this.props.navigation.state.params) {
MoviesService.getPopularMovies()
.then(movies => {
this.setState({movies: movies.results})
})
.catch(err => Alert.alert(err.toString()))
}
else {
this.setState({movies: this.props.navigation.state.params.data.results})
}
}
//...
嗯,最后一段代码执行了两次。第一次使用 "data" 参数未定义,第二次使用正确填充的参数。我的错误在哪里?谢谢大家:)
编辑:明确地说,这是上述问题的结果:
IMAGE
一段时间后,我意识到我可以通过用新的 DiscoverStackNavigator 替换 DiscoverScreen 然后将 DiscoverScreen、MoviesListScreen 和 MovieDetailsScreen 设置为其子屏幕来解决问题。所以我的代码现在看起来像这样:
抽屉导航器:
export default MenuNavScreen = DrawerNavigator(
{
Home: {
screen: HomeScreen
},
Movies: {
screen: MoviesStackNavigator
},
DiscoverMovies: {
screen: DiscoverStackNavigator
},
About: {
screen: AboutScreen
},
},
{
initialRouteName: 'Home'
})
DiscoverStackNavigator:
export default DiscoverStackNavigator = StackNavigator({
DiscoverMovies: {
screen: DiscoverScreen
}
DiscoverMoviesList: {
screen: MoviesListScreen
},
DiscoverMovieDetails: {
screen: MovieDetailsScreen
},
});
导航到 MoviesScreen:
onSearchConfirm() {
//...code before
return fetch(Configuration.TMDB_BASE_URL
.concat('/discover/movie?')
.concat(Utility.stringFromQueryParams({...params, api_key: Configuration.TMDB_API_KEY})))
.then(response => response.json())
.then(jsonResponse => {
_this.setState({searching: false});
const navigateAction = NavigationActions.navigate({
routeName: 'DiscoverMoviesList', // we changed the route name
params: {data: jsonResponse}
})
_this.props.navigation.dispatch(navigateAction)
})
.catch(err => console.error(err.toString()))
}
我不知道这是否是正确的方法,但效果很好。
我使用 React Navigation 在我的 React Native 应用程序的屏幕之间导航。我的屏幕结构是:
- DrawerNavigator
- HomeScreen
- MoviesStackNavigator
- MoviesListScreen
- MovieDetailsScreen
- DiscoverScreen
现在我想导航并将一些参数从 DiscoverScreen 传递到 MoviesListScreen。
这是我的代码:
DiscoverScreen.js
onSearchConfirm() {
this.setState({searching: true})
var params = {
sort_by: this.state.sortBy,
year: this.state.releaseYear,
with_genres: this.state.genreIds.join(',')
};
const _this = this;
return fetch(Configuration.TMDB_BASE_URL
.concat('/discover/movie?')
.concat(Utility.stringFromQueryParams({...params, api_key: Configuration.TMDB_API_KEY})))
.then(response => response.json())
.then(jsonResponse => {
_this.setState({searching: false});
const navigateAction = NavigationActions.navigate({
routeName: 'MoviesList',
params: {data: jsonResponse}
})
_this.props.navigation.dispatch(navigateAction)
})
.catch(err => console.error(err.toString()))
}
抽屉导航器:
export default MenuNavScreen = DrawerNavigator(
{
Home: {
screen: HomeScreen
},
Movies: {
screen: MoviesStackNavigator
},
DiscoverMovies: {
screen: DiscoverScreen
},
About: {
screen: AboutScreen
},
},
{
initialRouteName: 'Home'
})
电影堆栈导航器:
export default MoviesStackNavigator = StackNavigator({
MoviesList: {
screen: MoviesListScreen
},
MovieDetails: {
screen: MovieDetailsScreen
},
});
最后,我检查参数的代码 电影列表屏幕:
//...
componentWillMount() { //THIS IS CALLED TWICE
if(!this.props.navigation.state.params) {
MoviesService.getPopularMovies()
.then(movies => {
this.setState({movies: movies.results})
})
.catch(err => Alert.alert(err.toString()))
}
else {
this.setState({movies: this.props.navigation.state.params.data.results})
}
}
//...
嗯,最后一段代码执行了两次。第一次使用 "data" 参数未定义,第二次使用正确填充的参数。我的错误在哪里?谢谢大家:)
编辑:明确地说,这是上述问题的结果:
IMAGE
一段时间后,我意识到我可以通过用新的 DiscoverStackNavigator 替换 DiscoverScreen 然后将 DiscoverScreen、MoviesListScreen 和 MovieDetailsScreen 设置为其子屏幕来解决问题。所以我的代码现在看起来像这样:
抽屉导航器:
export default MenuNavScreen = DrawerNavigator(
{
Home: {
screen: HomeScreen
},
Movies: {
screen: MoviesStackNavigator
},
DiscoverMovies: {
screen: DiscoverStackNavigator
},
About: {
screen: AboutScreen
},
},
{
initialRouteName: 'Home'
})
DiscoverStackNavigator:
export default DiscoverStackNavigator = StackNavigator({
DiscoverMovies: {
screen: DiscoverScreen
}
DiscoverMoviesList: {
screen: MoviesListScreen
},
DiscoverMovieDetails: {
screen: MovieDetailsScreen
},
});
导航到 MoviesScreen:
onSearchConfirm() {
//...code before
return fetch(Configuration.TMDB_BASE_URL
.concat('/discover/movie?')
.concat(Utility.stringFromQueryParams({...params, api_key: Configuration.TMDB_API_KEY})))
.then(response => response.json())
.then(jsonResponse => {
_this.setState({searching: false});
const navigateAction = NavigationActions.navigate({
routeName: 'DiscoverMoviesList', // we changed the route name
params: {data: jsonResponse}
})
_this.props.navigation.dispatch(navigateAction)
})
.catch(err => console.error(err.toString()))
}
我不知道这是否是正确的方法,但效果很好。