React-Router: Component Isolation

Contents

GitHub Repos

πŸ’Ύ Ncoughlin: React-Streams-Client

πŸ’Ύ Ncoughlin: React-Streams-API

Intro

We will continue here working on our Twitch Clone Project called ”Glitchβ€œ.

current twitch progress

We are are currently working on creating the StreamEdit component, and have just completed a new route in our last post that directs us to this component, as well as passed in the data that was required as props. More on that in the last post React-Router: Variable Route Parameters.

There is a problem here that we need to watch out for, which is Component Isolation. Currently if we navigate to one of the routes to edit a stream manually, without clicking through from the Stream List, the application state will not have loaded any streams data yet, and therefore that state data will not be available to the StreamEdit component. This is because we have designed this component poorly so far. It relies on the user going to the stream list first, which is not always going to be the case.

This brings us to a very important React-Router concept. Every component must fetch it’s own data.

Luckily for us, we have already done part of this work. We wrote out all of our actions ahead of time, and we have one action that is designed to fetch a specific stream given an id.

actions/index.js
// fetch stream
export const fetchStream = (streamId) => async (dispatch) => {
  const response = await streams.get(`/streams/${streamId}`);

  dispatch({ type: FETCH_STREAM, payload: response.data });
};

and then we can go inside of our StreamEdit component and make use of this action to retrieve the data we need for the store and then retrieve it.

components/streams/StreamEdit.js
import React, { Component } from "react";
import { connect } from "react-redux";

import { fetchStream } from "../../actions";

class StreamEdit extends Component {
  componentDidMount() {    this.props.fetchStream(this.props.match.params.id);  }
  render() {
    console.log(this.props);  
    return <div>StreamEdit</div>;
  }
}

const mapStateToProps = (state, ownProps) => {
  // the stream that matches the ID in the URL
  return { stream: state.streams[ownProps.match.params.id] };
};

export default connect(mapStateToProps, { fetchStream })(StreamEdit);

and then we can quickly display that data.

components/streams/StreamEdit.js
import React, { Component } from "react";
import { connect } from "react-redux";

import { fetchStream } from "../../actions";

class StreamEdit extends Component {
  componentDidMount() {
    this.props.fetchStream(this.props.match.params.id);
  }

  render() {
    // if we have not retrieved stream yet use loading animation
    if (!this.props.stream) {
      return <div>Loading...</div>;
    }
    return (
      <>
        <h1>{this.props.stream.title}</h1>        <p>{this.props.stream.description}</p>      </>
    );
  }
}

const mapStateToProps = (state, ownProps) => {
  // the stream that matches the ID in the URL
  return { stream: state.streams[ownProps.match.params.id] };
};

export default connect(mapStateToProps, { fetchStream })(StreamEdit);

single stream data displayed