Im using React Router. In my state I have a number of TV shows identifiable by an ID. On the shows page I need to load the data for the specific show, matching the show ID to the end of the URL.
My state looks something like this but with more shows:
shows: [
{
id: 1318913
name: "Countdown"
time: "14:10"
},
{
id: 1318914
name: "The News"
time: "15:00"
}
]
In App.js:
<BrowserRouter>
<Switch>
<Route
exact
path="/"
render={() => {
return <Table shows={this.state.shows} />;
}}
/>
<Route
path="/show/:showID"
render={() => {
return <Show />;
}}
/>
<Route component={FourOhFour} />
</Switch>
</BrowserRouter>;
React Router makes the :showID part of the URL available on the shows page . So I could pass my entire show state to the Show component and then find the correct show from the url. However I imagine this is inefficient?
I was wondering if I should look up the show via the ID in App.js and only pass the correct show to the Show component. Is this better practice / more efficient?
Here is my Table component:
class Table extends Component {
render(props) {
return (
<table className="table table-striped table-bordered table-hover">
<tbody>
{
this.props.shows.map((item)=>{
return <TableRow
name={item.name}
time={item.time}
key={item.eppisodeId}
eppisodeId={item.eppisodeId}
img={item.img}
/>
})
}
</tbody>
</table>
)
}
}
Here is my TableRow component:
class TableRow extends Component {
render(props) {
const image = this.props.img !== null ?
<img src={this.props.img} alt={this.props.name} />
: null;
const showUrl = '/show/' + this.props.eppisodeId;
return (
<tr className="tableRow">
<td className="tableRow--imgTd">{image}</td>
<td><Link to={showUrl}>{this.props.name}</Link></td>
<td className="tableRow--timeTd">{this.props.time}</td>
</tr>
)
}
}
As I see in your question, you are using Link
to navigate. Considering you want to also send the data with the Link, you can pass an object to it instead of the string path
as mentioned in the React-router docs, So you can pass the show information with the state object
in TableRow
component like
const {name, time, episodeId, img} = this.props;
<Link to={{pathname:showUrl, state: {show: {name, time, episodeId, img }}}}>{this.props.name}</Link>
Now you can retrieve this information in Show
component as
this.props.location.state && this.props.location.state.name
The other thing that you need to take care of is, that you need to pass the props to the render function
<Switch>
<Route
exact
path="/"
render={(props) => {
return <Table shows={this.state.shows} {...props}/>;
}}
/>
<Route
path="/show/:showID"
render={(props) => {
return <Show {...props}/>;
}}
/>
<Route component={FourOhFour} />
</Switch>
Now the above solution will work only if you navigate from within the App, but if you change the URL it won't work, if you want to make it more robust, you would need to pass the data to the show component and then optimise in the lifecycle functions
You would . do it like
<Switch>
<Route
exact
path="/"
render={(props) => {
return <Table shows={this.state.shows} {...props}/>;
}}
/>
<Route
path="/show/:showID"
render={(props) => {
return <Show shows={this.state.shows} {...props}/>;
}}
/>
<Route component={FourOhFour} />
</Switch>
And then in the Show component
class Show extends React.Component {
componentDidMount() {
const {shows, match} = this.props;
const {params} = match;
// get the data from shows which matches params.id here using `find` or `filter` or whatever you feel appropriate
}
componentWillReceiveProps(nextProps) {
const {match} = this.props;
const {shows: nextShows, match: nextMatch} = nextProps;
const {params} = match;
const {params: nextParams} = nextMatch;
if( nextParams.showId !== params.showId) {
// get the data from nextProps.showId and nextShows here
}
}
}
However this is where libraries like redux
and reselect
are useful. with Redux your data shows
will be in one common store and you can access it in any component and reselect
gives you an option to create a selector that is memoized to get the appropriate show
data from shows
, so that the same calculation is not repeated again. Please explore about these and check if you find them a good fit for your project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With