I'm building a React Native app that works with JSON data and shows the upcoming movies. It looks like this: https://image.ibb.co/kuOt9m/app.png . My problem is whenever I click the Summary button I get all the summaries, for all the movies. What i want is to get a specific summary for the movie I clicked. In the JSON there's a movie id that is totally unique and I guess I should set it on the Button or the CardSection itself. My code looks like this:
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import axios from 'axios';
import MovieSummary from './MovieSummary';
class SummaryList extends Component {
state = { movies: [] };
componentDidMount() {
axios.get('https://api.themoviedb.org/3/movie/upcoming?api_key=22d8da68cffba151bfa886d5003aac02&language=en-US&page=1')
.then(response => this.setState({ movies: response.data.results }));
}
renderSummary() {
return this.state.movies.map(movie =>
<MovieSummary key={movie.id} movie={movie} />
);
}
render() {
console.log(this.state);
return (
<ScrollView>
{this.renderSummary()}
</ScrollView>
);
}
}
export default SummaryList;
then in another class i show the data like this:
import React from 'react';
import { View, Text } from 'react-native';
const MovieSummary = (props) => (
<View>
<Text>
{props.movie.overview}
</Text>
</View>
);
export default MovieSummary;
and then with a Router class (react-native-router-flux library) I use Router/Scene to connect the two screens. I'm gonna post the CardSection.js or Button.js code if it's gonna make it anymore clear and there's where I need to add an ID.
edit: adding more information
my CardSection.js looks like this:
import React from 'react';
import { View } from 'react-native';
const CardSection = (props) => (
<View style={styles.containerStyle}>
{props.children}
</View>
);
const styles = {
containerStyle: {
*some view styles*
}
};
export default CardSection;
my Button.js looks like this:
import React from 'react';
import { Text, TouchableOpacity } from 'react-native';
const Button = ({ onPress, children }) => (
<TouchableOpacity
onPress={onPress}
style={styles.buttonStyle}
>
<Text style={styles.textStyle}>
{children}
</Text>
</TouchableOpacity>
);
const styles = {
buttonStyle: {
*button styles*
},
textStyle: {
*text styles*
}
};
export default Button;
First thing, I think there's a bit of confusion about your second screen, you're calling it SummaryList
and it's working on an array of movies - whereas if I understand correctly you want your second screen to just deal with one movie.
I'd rename a few things:
MoviesList
is fineMovieDetail
-> MoviesListItem
(these are rows in your MovieList
, renaming to avoid confusion with your second screen)SummaryDetail
is fine (this will be your single-movie scene. I'd probably actually call this MovieDetail
but that would get confusing!)Forget about SummaryList
- we don't need it. You only have one list we're concerned about, that's MoviesList
.
First, modify your Router
so that you have a MoviesList
and a SummaryDetail
scene:
// Router.js
// ...
const RouterComponent = () => (
<Router
navigationBarStyle={styles.viewStyle}
titleStyle={styles.textStyle}
sceneStyle={{ paddingTop: 53 }}
>
<Scene key="upcoming" component={MoviesList} title="Upcoming Movies" />
<Scene
key="summaryDetail"
component={SummaryDetail}
title="Summary Detail"
leftButtonIconStyle={{ tintColor: '#a52a2a' }}
/>
</Router>
);
// ...
So now your MoviesListItem
is the component with a summary Button
in it. This needs to lead to your SummaryDetail
scene. You can navigate to your SummaryDetail
scene by calling Actions.summaryDetail()
from react-native-router-flux
, but you actually want to tell this scene which movie it's dealing with. Pass the movie (which you already have as a prop of MovieListItem
) as a param, via an argument to Actions.summaryDetail(...)
like this:
// MovieListItem.js
// ...
<View style={{ justifyContent: 'flex-end' }}>
<Button
onPress={() => {
Actions.summaryDetail({ movie: props.movie }); // <- Important bit!
}}>
Summary
</Button>
</View>
// ...
Now, you should have the movie available in your SummaryDetail
screen as the movie
prop.
// SummaryDetail.js
// ...
const SummaryDetail = (props) => (
<View>
<Text>
{props.movie.overview}
</Text>
</View>
);
// ...
You might want to split off parts of SummaryDetail
into separate presentational components later, and you might want to turn it into a class and use componentDidMount
to fetch some extra movie detail you don't already have. But this should be enough to get you started with one movie on a second screen.