2

I have worked with React and Typescript and fetch a data from API. After fetching data, it will be saved as coin object. And I absorb at the pending state, it may not have a data. So, coin can be null. If coin is null. Then it is no way we can get a field image of that object. Does anyone work on this before? Please give me some ideas. I don't have experienced with typescript. Here is my code:

import React, { Component } from 'react'
import axios from 'axios';
import CoinIcon from './CoinIcon';
interface CoinDetailProps{
    id:string;
}
interface CoinImage {
    thumb: string ;
    small: string ;
    large: string ;
  }
interface Coin {
    id: string,
    symbol: string,
    name: string,
    image: CoinImage | null,
    description: string
  }
  interface CoinState{
      coin : Coin;
      loaded: boolean;
  }
  
export class CoinDetail extends Component<CoinDetailProps,CoinState> {
    constructor(props) {
        super(props)
    
        
        const init = {} as Coin;
        this.state = {
             coin : init,
             loaded: false,
             
        }
    }
    loadData = () => {
        const {id} = this.props;
        const url = `https://api.coingecko.com/api/v3/coins/${id}`;
        
        axios.get(url)
          .then(response => {
            const data = response.data
            
            this.setState({
              coin: data,
              loaded: true
            })
          })
          .catch((error) => {console.log("Something went wrong. ", error)})
      }
      componentDidMount() {    
        this.loadData();
      }
    
      componentDidUpdate(prevProps, prevState) {    
        if (prevProps !== this.props) {
          this.loadData();
        }
      }
    render() 
    {
        const {loaded, coin} = this.state;
        console.log("coin image:" + coin.image.small)
        return (
            <div>
                <CoinIcon name={coin.name} symbol = {coin.symbol} image={coin.image.small} />
            </div>
        )
    }
}

export default CoinDetail

When I try to print out like :

console.log(coin.image.small) <=== error here: Object is possibly 'null'.
Nhan Le
  • 53
  • 1
  • 4
  • 1
    "*So, `coin` can be null*" - that's not what the error message says. `coin.image` can be `null`. – Bergi May 21 '21 at 15:09
  • @Bergi: if coin is null then null.image will be a error. – Nhan Le May 21 '21 at 15:11
  • But `coin` is not null. You declared it to be type `Coin` (as part of `CoinState`), and you initialised it with an (empty) object. As I said, the warning is not about `coin`, it's about `.image`, on which you must not access `.small` before checking whether the `image` is non-null. – Bergi May 21 '21 at 15:15

1 Answers1

0

You can explicitly check:

if (coin.image) {
    console.log(coin.image.small);
} else {
    // Do something else
}

Or you can use optional chaining:

console.log(coin.image?.small);
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • It will work. However, I am handling to pass it to ```CoinIcon``` component. I really need to avoid null. – Nhan Le May 21 '21 at 16:09
  • So use the else branch to get a `` component with a different, maybe hardcoded, prop … or no `` at all. – Quentin May 21 '21 at 16:11