Below code returns an error for me
Uncaught (in promise) TypeError: Cannot read property 'setState' of undefined
I am new to react and this seems very basic. Any suggestion what could I be doing wrong. From the json result I want to store all names in my array.
import React, { Component } from "react";
class Search extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
}
}
Search() {
fetch("http://url/getSearchResults")
.then(res => res.json())
.then(
(res) => {
this.setState({
list: res.data.name
})
})
}
This is a very common problem with classes in React - there are two ways to solve this problem:
Bind your methods in the constructor:
constructor(props) {
super(props);
this.state = {
list: [],
}
this.Search = this.Search.bind(this);
}
Use an arrow function instead:
search = () => { ... }
See this post for more information.
Note: using componentDidMount() will be useful if you are trying to make the fetch call on mount - the answer above addresses the issue of this being undefined as per the error you are seeing.
Add componentDidMount() to Search(), it is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here.Its a good place to load data from a remote endpoint.
Related
In my React.js app, I am fetching a quote from API and storing it in the state object, When trying to access the properties of the object which is stored in state. Returning null.
Code:
import React, { Component } from "react";
export default class Quotes extends Component {
constructor(props) {
super(props);
this.state = {
quote: null,
};
}
componentDidMount() {
fetch("https://quote-garden.herokuapp.com/api/v2/quotes/random")
.then((response) => response.json())
.then((quote) => this.setState({ quote: quote.quote }))
.catch((error) => console.log(error));
}
render() {
console.log(this.state.quote.quoteText); //This is returning null
console.log(this.state.quote); //This is working fine.
return (
<div>
<p>// Author of Quote</p>
</div>
);
}
}
I am new to React.js, I spining my head for this problem around 2 hourse. I didn't get any solution on web
output showing quote object
When I try to console.log(this.state.quote) it prints out this output, well it is fine.
and when I try console.log(this.state.quote.quoteText) It will return can not read property
output showing can not find property
You must note the you are trying to fetch data asynchronously and also you fetch data in componentDidMount which is run after render, so there will be an initial rendering cycle wherein you will not have the data available to you and this.state.quote will be null
The best way to handle such scenarios is to maintain a loading state and do all processing only after the data is available
import React, { Component } from "react";
export default class Quotes extends Component {
constructor(props) {
super(props);
this.state = {
quote: null,
isLoading: true,
};
}
componentDidMount() {
fetch("https://quote-garden.herokuapp.com/api/v2/quotes/random")
.then((response) => response.json())
.then((quote) => this.setState({ quote: quote.quote, isLoading: false }))
.catch((error) => console.log(error));
}
render() {
if(this.state.isLoading) {
return <div>Loading...</div>
}
console.log(this.state.quote.quoteText); //This is returning proper value
console.log(this.state.quote);
return (
<div>
<p>// Author of Quote</p>
</div>
);
}
}
When you are accessing the quoteText without checking whether the key in the object is present or not it throws an error -
render(){
if(this.state.quote && this.state.quote.hasOwnProperty('quoteText')){
console.log(this.state.quote.quoteText);
}
}
I'm building a google book search app, and before I even start I open up the inspect and I see on my console
"Warning: Can't call setState on a component that is not yet mounted".
Also, just to see what other errors that come up I did a book search and the error that I am getting back says
"TypeError: Cannot read property 'print-type' of null". And the console is pointing to this line of code as the problem "this.state["print-type"]"
I'm new to react so right now I am all thumbs do I need to put a componentDidMount within my handler or will I need to further bind this handler in order for it to work?
In my constructor I have inserted this.handleSearch = this.handleSearch.bind(this) thinking that this will solve my problem with
"Can't call setState on a component that is not yet mounted."
but this did not work.
constructor(props) {
super(props);
this.setState({
"print-type": "all",
filter: "ebooks"
});
this.handleSearch = this.handleSearch.bind(this);
}
changeFilter(e) {
const filter = e.target.value();
this.setState({
filter
});
}
changePrintType(e) {
const printType = e.target.value();
this.setState({
"print-type": printType
});
}
handleSearch(q) {
console.log(this.state);
const key = "AIzaSyAJ448LHnJ0N6XxzOyIRfhJFveQzwHU_Ms";
const baseurl = "https://www.googleapis.com/books/v1/volumes";
const url = `${baseurl}?q=${encodeURIComponent(q)}&key=${key}&print-type=${
this.state["print-type"]
}&filter=${this.state.filter}`;
const options = {
headers: {
"Content-Type": "application/json"
}
};
I expect to see all books with the same title I search for.
The correct way of initialising the state is -
this.state = {
print-type: "all",
filter: "ebooks"
};
The correct way of setting the state is -
this.setState({
print-type: printType
});
"Warning: Can't call setState on a component that is not yet mounted" is the result of setState() inside constructor(). You need to change it to this.state because you're just defining your state there.
We never write setState in constructor,
constructor(props) {
super(props);
this.setState({
"print-type": "all",
filter: "ebooks"
});
this.handleSearch = this.handleSearch.bind(this);
}
You need to define state,
constructor(props) {
super(props);
this.state ={
print_type: "all", //never write state name like `print-type`, use underscore instead
filter: "ebooks"
}
this.handleSearch = this.handleSearch.bind(this);
}
Whenever you want to use print_type write like , this.state.print_type.
For setState,
this.setState({print_type:printType})
I'm new to React and been struggling a lot at rendering a list of users for a simple user management table I'm trying to build. If anyone is able to see where I went wrong with this it would be greatly appreciated if you could let me know as I've been spending a ton of time on it and reading everything I could find but still have had no success.
I've tried many different variations but this is what I currently have:
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import PropTypes from 'prop-types';
class ManageUsers extends React.Component {
constructor(props) {
super(props);
this.state = {
users: []
};
}
renderUsers() {
return this.props.users.map((users) => {
return <ManageUsers key={users._id} user={users}/>;
});
};
render() {
return (
<div>
<li>{this.renderUsers()}</li>
</div>
);
}
};
ManageUsers.propTypes = {
users: PropTypes.array.isRequired
};
export default withTracker(() => {
Meteor.subscribe("users");
return {
users: Meteor.users.find({}).fetch()
}
})(ManageUsers);
I receive a few different errors with this in my browser console including:
Uncaught TypeError: Cannot read property 'map' of undefined
Warning: Failed prop type: The prop users is marked as required in
ManageUsers, but its value is undefined.
Uncaught TypeError: Cannot read property 'map' of undefined
Either test that users is defined before mapping, or give it a default prop value.
renderUsers = () => {
const { users } = this.props;
return users && users.map(user => <ManageUsers key={user._id} user={user}/>);
};
or
ManageUsers.defaultProps = {
users: [],
};
Warning: Failed prop type: The prop users is marked as required in ManageUsers, but its value is undefined.
This usually means that although it's a required prop you probably aren't passing it defined data from the parent component.
In this case, it appears the Meteor HOC isn't providing the users data when the react component is mounting. I'm not familiar with Meteor, but perhaps you could make the subscribe function async, and await for it to resolve with a value for the users prop.
export default withTracker(async () => {
Meteor.subscribe("users");
return {
users: await Meteor.users.find({}).fetch()
}
})(ManageUsers);
In my code I tell the API to retrieve the data from the end point inside componentDidMount().
componentDidMount() {
this.setState({
lessons: API.getAllLessons()
})
}
Then I map each item inside the list to an individual panel inside the render
render() {
return (
this.state.lessons.map((lesson)=>{
<LessonItem lesson={lesson}/>
})
);
}
However, it throws an error when mapping as the property in the state it's trying to map is null, but it shouldn't be as data is returned from the API.
Uncaught (in promise) TypeError: Cannot read property 'lessons' of null
My state gets defined like so
export interface AuthenticatedHomeState {
currentUser: any;
lessons: any;
}
you probably didn't initialised the state.
constructor(props){
super(props)
this.state = {
lessons: [] //default value
}
}
componentDidMount() {
this.setState({
lessons: API.getAllLessons()
})
}
However, if API.getAllLessons returns a Promise you will need to handle it differently.
you are calling componentDidMount, meaning it will run after render had been called. You need to call componentWillMount()
You have to intialise the state first, then call the api, and if the api call is a promise call(which usually is) you will have to read the values in such a way,
constructor(props){
super(props)
this.state = {
lessons: [] //set default value for lessons
}
}
componentDidMount() {
API.getAllLessons().then((resp)=>{
this.setState({
lessons: resp.data
})
})
}
I am actually at a loss to figure out why this isn't working as I have spent a lot more hours than usual on how to get it fixed. The problem is I am using axios to make a REST call to get the data to be rendered. Inside the block to handle the response, even though I am able to retrieve the data the 'this' object somehow fails to refer to the correct object and I get an error. I dono why this is happening but any help on it will be highly appreciated.
Posting my code snippet below. I have tried saving the context of this outside the axios call scope and used the new variable but that too does not help. Here is the error I get in my console
TypeError: _this2.setState is not a function
import React, {Component} from 'react';
import axios from 'axios';
import './RouteList.css';
class RouteList extends Component{
constructor(){
super();
this.setState = {
allRoutes: {},
selectedRoutes: {}
};
}
componentDidMount(){
const that = this;
//Retrieve the SF-Muni route list
axios.get('http://webservices.nextbus.com/service/publicJSONFeed?command=routeList&a=sf-muni')
.then(response => {
console.log(response);
that.setState({ allRoutes: response.data.routes });
})
.catch((error) => {
console.log(error);
});
}
render(){
return (
<div className="transit-routes">
{/*TODO-Code to render data.*/}
</div>
);
}
}
export default RouteList;`
The problem is that you are overwriting the setState method in the constructor, try to set the initial state like this:
this.state = {
allRoutes: {},
selectedRoutes: {}
};
Also, when using an arrow function, there's no need to save the parent scope, the function will run under the same scope as the outer function.