0

I have three js files. The parent I am to call the child classes. The code goes like this.

This is the parent class App.js

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import {FirstPage} from './FirstPage.js';
import {Panorama} from './Panorama.js';
import {BrowserRouter,Route,Router,Switch} from 'react-router-dom';

class App extends React.Component{
    constructor(props){
      super(props);
    }

    render(){
      return(
        <div>
          <BrowserRouter>
            <Switch>
              <Route exact path="/" component={FirstPage} />
              <Route path=":id" component={Panorama} />
            </Switch>
          </BrowserRouter>
        </div>
        )
    }
  }

ReactDOM.render(<App/>,document.getElementById('container'));

The FirstPage.js is something like this

import React from 'react';
import ReactDom from 'react-dom' ;
import $ from 'jquery' ;
import {Panorama} from './Panorama.js';
import {Redirect,Link} from 'react-router-dom';
import {withRouter} from 'react-router';

class FirstPage extends React.Component{
    constructor(props){
      super(props);
      this.state={
        list:[],
        images:[],
        isClicked:false,
        redirect:true,
        imageUrl:''
      }
      this.loadImages=this.loadImages.bind(this);
      this.loadOne=this.loadOne.bind(this);
    }
    componentDidMount(){
        window.addEventListener('load',this.loadImages);
   }

   loadImages(){ 
      console.log("load");
      var that=this;
      $.ajax({
        type:'GET',
        url:'https://demo0813639.mockable.io/getPanos',
        datatype:'jsonp',
        success:function(result){
          var images=that.state.images;
          for(var i=0;i<result.length;i++){
            that.state.images.push({"pano":result[i].pano,"name":result[i].name});
          }
          that.setState({
            images:images
         })
        }

      })
   }

   loadOne(pano){
    console.log("pano: ",pano);
    this.setState({
      isClicked:true,
      imageUrl:pano
    })
    //this.props.history.push(`/image/${pano}`)
  }

  render(){
    var list=this.state.list;
    console.log("Image URL: "+this.state.imageUrl);
    return this.state.isClicked?<Link to={`${this.state.imageUrl}`}/>:
        <div> {this.state.images.map((result)=>{
        return(<div className="box">
                <div className="label">{result.name}</div>
                  <img src={result.pano} className="image col-md-3" onClick={this.loadOne.bind(this,result.pano)}/>   
              </div>
              )

       })}
       </div>
  }
}

module.exports={
  FirstPage:FirstPage
}

This page makes an ajax call and loads four images on the screen.If clicked on one of those images, another js file is supposed to be called with the id of that image so that the particular image can be seen in full screen.

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import {Link} from 'react-router-dom';

class Panorama extends React.Component{
    render(){
      console.log("Image: "+ props.match.params.id);
      return( 
        <div>
          <img src={`${props.match.params.id}`}/>
          </div>
        )
    }
  }

module.exports={
  Panorama:Panorama
}

Although I get no errors in the console, after clicking on an image nothing is coming up on the screen. What is wrong with the code?

The version of React router is v4.

Aayushi
  • 1,736
  • 1
  • 26
  • 48

2 Answers2

1

First thing you need to do as @Fawaz suggested, update your Route

<Route path="/panorama/:imageUrl" component={Panorama} />

As you are sending the url as parameter, you need to encode the url before loading image, and you can change the route using history API, no need to use the Link in your render method on some state change. I think the approach is wrong. I have updated the loadOne method as below:

  loadOne(pano){
   let imageUrl = encodeURIComponent(pano);
   this.props.history.push(`/panorama/${imageUrl}`);
  }

In Panorama Component, you can decode the url and load the image.

  render() {
     let url = decodeURIComponent(this.props.match.params.id);
     return( 
       <div>
         <img src={`${url}`}/>
       </div>
     )
  }

FirstPage.js

import ReactDom from 'react-dom' ;
import $ from 'jquery' ;
import {Panorama} from './Panorama.js';
import {Redirect,Link} from 'react-router-dom';
import {withRouter} from 'react-router';

class FirstPage extends React.Component{
   constructor(props){
     super(props);
     this.state={
       images:[]
     }
  this.loadImages=this.loadImages.bind(this);
}
componentDidMount(){
  window.addEventListener('load',this.loadImages);
}

loadImages(){ 
  var that=this;
  $.ajax({
    type:'GET',
    url:'https://demo0813639.mockable.io/getPanos',
    datatype:'jsonp',
    success:function(result){
      that.setState({
        images:result // I am assuming, result is array of objects.
     })
    }
   })
}

loadOne(pano){
  let imageUrl = encodeURIComponent(pano);
  this.props.history.push(`/panorama/${imageUrl}`);
}

render(){
   return <div> 
           {this.state.images.map((result)=>{
              return(<div className="box">
                <div className="label">{result.name}</div>
                <img src={result.pano} className="image col-md-3" 
                onClick={this.loadOne.bind(this,result.pano)}/>   
                </div>)

           })}
          </div>
  }
}

module.exports={
  FirstPage:FirstPage
}
Dev
  • 3,922
  • 3
  • 24
  • 44
  • So what am I supposed to return in FirstPage.js ? I mean how do I switch to Panorama.js – Aayushi Aug 10 '17 at 07:50
  • You have to change the Route path in App.js. In FirstPage.js, you dont have to maintain this many states. You can have only images state, and on load, you can update images state. – Dev Aug 10 '17 at 07:56
  • Even if i do that, no image comes up on the screen after clicking – Aayushi Aug 10 '17 at 07:57
  • And is there a way to hide the imageUrl from the server's URL – Aayushi Aug 10 '17 at 08:00
  • 1
    @Aayushi, I have added the FirstPage.js code sample. Please try and relate. Regarding, hiding the params from url, I am aware of using encoded url string. Their might be some additional option in history api, which you can explore – Dev Aug 10 '17 at 09:20
0

Your path needs to match the one you're calling. Change your second route to :

<Route path="/image/:id" component={Panorama} />
Fawaz
  • 3,404
  • 3
  • 17
  • 22