1

I'm putting together a cryptocurrency app as an experiment and I'm pulling data from an API. I've managed to get all the data to display nicely and search for a price change every two seconds but I'd like to temporarily add a class to the updated DOM element when the price changes, red if down and green if up. I'm currently mapping out each item from the API and only wish to add the required class to the updated item (currency) in the DOM. Not all items.

Please see my code below:

import React, { Component } from "react";
import { Link } from "react-router-dom";

import "./home.scss";

class Home extends Component {
  // Create initial state and pass props
  constructor(props) {
    super(props);
    this.state = {
      isLoading: true,
      coins: []
    }
  }

  // Custom fetch data method
  fetchData() {

      // Fetch data
      fetch('http://coincap.io/front')
      // Turn response into JSON
      .then(response => response.json())
      // Take parsedJSON and log results
      // Create individual object for each of the users
      .then(parsedJSON => parsedJSON.map(coin => (
          {
              long: `${coin.long}`,
              short: `${coin.short}`,
              price: `${coin.price}`
          }
      )))
      // Overwrite empty array with new contacts
      // Set array to contacts state and set isLoading to false
      .then(coins => {
        this.setState({
            coins,
            isLoading: false
        })
      })
      // Catch the errors
      .catch(error => console.log('parsing failed', error))
  }


  componentDidMount() {
    setInterval(() => {
      this.fetchData();
      console.log('refreshed'); 
    }, 2000);
  }

  render() {
    const { isLoading, coins } = this.state;
    return (
      <div className="container__wrap container__wrap--home">
        <div className={`content ${isLoading ? "is-loading" : ""}`}>
          <div className="panel">
            {
            !isLoading && coins.length > 0
              ? coins.map(coin => {
                  // Destruct each of the items in let variable
                  let { long, short, price } = coin;
                  return (
                    <div className="panel__item" key={short}>
                      <p>Name: {long}</p>
                      <p>Short: {short}</p>
                      <p>Price: ${price}</p>
                      <Link className="button" to={`/${short}`}>
                        View Coin
                      </Link>
                    </div>
                  );
                })
              : null}
          </div>
          <div className="loader">
            <div className="loader__icon" />
          </div>
        </div>
      </div>
    );
  }
}

export default Home;

In short, I'd like to temporarily add a class to 'panel__item' each time that element updates.

Thanks in advance!

1 Answer 1

1

It may be easier if you made a <Coin /> component so you could keep track of the changes in componentWillReceiveProps and manage the state of each individual coin.

Try something like this:

class Coin extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
       color: grey,
    };
  }

  componentWillReceiveProps(newProps) {
    if (this.props.price > newProps.price) {
      this.setState({ color: 'red' });
    } else if (this.props.price < newProps.price) {
      this.setState({ color: 'green' });
    } else {
      this.setState({ color: 'grey' });
    }
  }

  render() {
    const { long, short, price } = this.props;
    return (
       <div className={`panel__item ${this.state.color}`} key={short}>
         <p>Name: {long}</p>
         <p>Short: {short}</p>
         <p>Price: ${price}</p>
         <Link className="button" to={`/${short}`}>
            View Coin
         </Link>
       </div>
     );  
  }
}

Then just invoke this component in your map and pass the variables as props.

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

7 Comments

Thanks Max, I've created a new component and passed props. Appears to be displaying correctly but unfortunately the class stays at grey and never changes. Should I be running componentWillReceiveProps in the parent file instead? Just an idea. Thanks
I'm not sure what you mean. componentWillReceiveProps is automatically invoked every time Coin receives new props. it should be defined in the Coin component. If that doesn't work console.log the newProps and this.props inside of it.
Looks like the argument should be nextProps instead of newProps (reactjs.org/docs/react-component.html#componentwillreceiveprops) I've changed this but still no joy. console log messages are not appearing which makes me think it isn't triggered.
The name of the argument shouldn't make a difference. Are you sure you are passing the price variable as a prop to Coin?
I've used the following: <Coininfo key={Math.random()} price={price} short={short} long={long} /> I can see the dom updating in console but no log messages. Values are appearing fine.
|

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.