John Rogerson
John Rogerson

Reputation: 1183

Trouble Setting State in React

I'm calling an API (in Node) from my react component (Stats.js)

This function getName is taking a passed in prop (called 'value') in order to look up a value in MongoDB. See code below:

/* Stats React Component --Stats.js*/
class Stats extends Component {
    constructor(props) {
    super(props);

    this.state = {
       marketdata: [],
       value: '',
       name: ''
    }
    }


  componentDidMount() {
    const {value, name} = this.state;
    this.getName(value);
    this.getData(name);
   }

     getName = (value=this.props.value) => {
       value = value.replace(/"/g,"");
       console.log('Value', value);
       fetch(`/stats?ticker=${value}`)
      .then(res => console.log('Response', res))
      .then(results => {
         this.setState({
             name: results,
    })
    })

}

   componentWillReceiveProps(nextProps) {
      this.setState({value: nextProps.value });
    }


   getData = (name=this.state.name) => {
    fetch(`https://api.coinmarketcap.com/v1/ticker/${name}/?convert=USD`)
    .then(res => res.json())
    .then(results => {
     this.setState({
        marketdata: results,
     })
     })

     render() {
  const {marketdata} = this.state;



     return (
            <div className="App">
            {marketdata.map(data =>
              <div key={data.id}>
                <span>Price: {numeral(data.price_usd).format('$0.00')} </span>
                <span>24 Hour Volume: {numeral(data["24h_volume_usd"]).format('$0.0a')} </span>
                <span>Pct Change (24 Hrs): {(numeral((data.percent_change_24h)/100).format('0.0%'))} </span>
                <span>Market Cap: {numeral(data.market_cap_usd).format('$0.0a')}</span>
              </div>
            )}
            </div>
        );
    }
}

export default Stats;

As an example, this passed in prop (value) looks like this "BTC"--i can verify in developer console that the value of state is working correctly

I'm trying to set the state of the 'name' variable to the data returned from the API lookup, the method called getName.

I can also verify in express that the data is being retrieved correctly on the backend. This is my express file that is called by getName

/* GET coin stats.  stats.js */
router.get('/', (req, res, next) => {
  let ticker = req.query.ticker;
  console.log(ticker);
  Stat.findOne({symbol:ticker})
    .then(function(result) {
      var stats = result;
      console.log(stats.name);
      res.json(stats.name);
    })
    .catch(function(err) {
      console.log('caught error', err.stack)
      res.send({ error: err })
    })
});

Note my data in the database looks like this: symbol: "BTC", name: "Bitcoin", thus when a user enters BTC i need name to set state to 'Bitcoin"

If I do a http://localhost:3001/stats?ticker=BTC is does indeed return "Bitcoin"

However for some reason the state of 'name' is not changing when a user inputs a value and my Stats.js component receives a new value.

Anyone see any problems here?

Upvotes: 0

Views: 44

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281646

getName and getData are only called, in componentDidMount which is called only once. You need to call them when you update the value in componentDidUpdate too, when the state updates with the new value from componentWillReceiveProps function. Also provide a check in componentWillReceiveProps function before setting state

componentWillReceiveProps(nextProps) {
  if(this.props.value !== nextProps.value) {
      this.setState({value: nextProps.value });
  }
}

componentDidMount() {
    const {value, name} = this.state;
    this.getName(value);
    this.getData(name);
}

componentDidUpdate(prevProps, prevState) { 
  if(this.state.value !== prevState.value) {
      this.getName(this.state.value);
  }
  if(this.state.name !== prevState.name) {
      this.getData(this.state.name);
  }
}

Upvotes: 2

Related Questions