Reputation: 1543
I'm trying to query an API to use the data in a react native app but am running into a problem with accessing data I store in the state. Basically, I am trying to access a markets object which is stored in the state. If I examine the state, I see the markets object is properly set. However, as soon as I try to do anything with the markets object, I encounter an error that says Cannot read property 'markets' of null
.
Why is this happening and how can I fix this issue?
I included the code that causes the issue below. I appreciate any suggestions.
export default class cryptoTracker extends Component {
constructor(props) {
super(props);
this.opts = {
baseUrl: 'https://bittrex.com/api/v1.1',
apikey: 'APIKEY',
apisecret: 'APISECRET',
};
this.updateMarkets();
}
updateMarkets(){
axios.get(this.opts.baseUrl + '/public/getmarkets').then((response) => {
this.setState({'markets' : response.data.result});
}
).catch((error) => {
console.log(error.name)
console.log("Error");
});
}
render() {
console.log("The state is below");
console.log(this.state);
//This line causes the issue
console.log(this.state.markets);
return(
<View>
</View>);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('cryptoTracker', () => cryptoTracker);
Upvotes: 3
Views: 1018
Reputation: 104379
Reason is, you didn't define the state
variable in constructor
. Api call be asynchronous so when you get data and do setState
, after that only state
will be available (before that state
will be null
), render will get executed before that and when it will try to access the value this.state.makers
, it is throwing the error:
Cannot read property 'markets' of null
Changes:
1. Define the state
object and define the makers
inside that, like this:
constructor(props) {
super(props);
this.state = {
makers: {}
}
this.opts = {
baseUrl: 'https://bittrex.com/api/v1.1',
apikey: 'APIKEY',
apisecret: 'APISECRET',
};
}
2. Use componentDidMount lifecycle method and do the api call inside that, like this:
componentDidMount(){
this.updateMarkets();
}
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.
3. Name of the component must start with a uppercase letter, so use CryptoTracker instead of cryptoTracker.
Upvotes: 3