0

I'm a beginner in React, in the componentDidMount, I'm retrieving a response object from Axios then I'm setting it to the state object, even though it is accessible from outside functions it wouldn't work inside the render method, I don't know how to bind the state to get access to render()

error that pops: Unhandled Rejection (TypeError): Cannot read property 'imageref' of undefined

export default class Product extends Component {
  constructor(props) {
    super(props);
    const id = this.state.comicId;
    console.log("This is printed from the constructor " + id);
  }

  state = {
    comicId: "",
    issueObjectState: "",
  };
render(){
<img
 src={this.state.issueObjectState.imageref}
 alt="Image Description"
 className="mx-auto img-fluid"/>
}
 
async componentDidMount() {
    let state = [];
    const id = this.props.location;
    let comicId = id.data;
    this.setState({ comicId: this.props.comicId });

    let issueData = await axios.get(`http://localhost:5000/comic/${comicId}`);
    let comicData = issueData.data;

    if (comicData) {
      this.setState({ issueObjectState: comicData });
      console.log(this.state.issueObjectState);
    }
  }
}


help is much appreciated

3
  • Would be useful to show the offending code. Btw, you are assigning this.props.comicData to the issueObjectState. Why is that? Commented Sep 7, 2020 at 12:08
  • Can you check your api data is coming or not? Commented Sep 7, 2020 at 12:15
  • yes i consoled and it works Commented Sep 7, 2020 at 12:23

6 Answers 6

1

I see that you have many errors on your code, starting with declaring the state outside the constructor method, so you should do this first :

constructor(props) {
super(props);
this.state = {
comicId: "",
issueObjectState: "",
};
}

then lifecycle methodes can't be used with the async keyword before it, your async function must be inside the lifecycle method.

Sign up to request clarification or add additional context in comments.

Comments

1

What I believe here is you have to shift your this.state object to the constructor.

export default class Product extends Component {
 constructor(props) {
  super(props);
  state = {
    comicId: "",
    issueObjectState: "",
  };
  const id = this.state.comicId;
  console.log("This is printed from the constructor " + id);

 }
}

Comments

0

You are trying to access the object this.state.issueObjectState.imageref before you assign an object to issueObjectState. At the time of the error the issueObjectState is simply ""

render is called before componentDidMount. What you could use instead is componentWillMount to assign an object to issueObjectState. But it would be best practice to avoid componentWillMount alltogether and maybe in your case just assign it an object with a value of null

Comments

0

Use it like :

   <img src={this.state.issueObjectState!==""?
    this.state.issueObjectState.imageref : this.state.issueObjectState }
    alt="Image Description" className="mx-auto img-fluid"/>

Comments

0

Several flaws in your component.

  1. You are accessing state inside the render method before the data is fetched and stored to the state. Axios fetch the data asynchronously and it won't be available inside the initial call of render method. Better add a check before accessing state data.

  2. You are not returning any element or component from the render method which is incorrect.

Refactoring the render part as bellow should work:

render(){
 return (
 this.state.issueObjectState == '' ? null : 
 <img
  src={this.state.issueObjectState.imageref}
  alt="Image Description"
  className="mx-auto img-fluid"/>
 )
}

Comments

0
async componentDidMount() {
    let state = [];
    const id = this.props.location;
    let comicId = id.data;
    this.setState({ comicId: this.props.comicId });

    let issueData = await axios.get(`http://localhost:5000/comic/${comicId}`);
    let comicData = issueData.data;

    if (comicData) {
      this.setState({ issueObjectState: comicData });
      console.log(this.state.issueObjectState);
    }
  }
}

should be:

componentDidMount() {
    const  {comicId} = this.state

    axios.get(`http://localhost:5000/comic/${comicId}`).then((issueData)=> {
      this.setState({ issueObjectState: issueData.data ? issueData.data : null });
      //console.log(this.state.issueObjectState); <-- does not work this.setState is like async
        }
});

      }
    }

and:

constructor(props) {
  super(props);
  this.state = {
   comicId: props.location.data,
   issueObjectState: "",
};
}

render:

render(){
 return (
  <div>
    {this.state.issueObjectState &&
    <img
      src={this.state.issueObjectState.imageref}
      alt="Image Description"
      className="mx-auto img-fluid"/>
    }
  </div>
 )
}

or:

render(){
 if (this.state.issueObjectState) 
 return (
    <img
      src={this.state.issueObjectState.imageref}
      alt="Image Description"
      className="mx-auto img-fluid"/>
 )
 return <Loading />  //<--- a compenent that show an animated loading image
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.