moody1208
moody1208

Reputation: 559

React passing state Objects to child component

I am new to using React and have run into an issue with passing state.

I have a get request in my App.js which I am using to add and Object containing Objects to state. I am then trying to pass this data to a component to loop over the objects and display the data.

the problem is the data isn't getting picked up in the component, it just returns currencies [object object]. If I add everything directly to the Component, rather than passing state down, then everything works as expected.

Also in my component i've had to comment out this.createTable() as this causes the following error:

×
TypeError: Cannot convert undefined or null to object
// Get the keys of the first item.
> 60 | Object.keys(Object.values(data)[0]).forEach(key => {
     | ^  61 |   const header = document.createElement('th');
  62 |   header.textContent = key;
  63 |   headerRow.append(header);

If anyone can point me in the right direction it would be appreciated!

App

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      error: null,
      isLoaded: false,
      currencies: {}
    };
  }

  componentDidMount() {

    axios.get('https://blockchain.info/ticker') 
      .then((response) => {

        const data = response.data; // Returns an Object containing multiple Objects

        this.setState({
          currencies: data,
          isLoaded: true
        });

      },
      (error) => {
        console.log(error);
      });

  } 

  render() {

    const currencies = this.state.currencies; 
    
    return (
      <div className="app">
        <div className="app__col">
          <CurrencyData currencies={currencies} />
        </div>
        <div className="app__col">
          <p>FORM</p>
        </div>
      </div>
    );
  }
} 
export default App;

Component

class CurrencyData extends Component {


  componentDidMount() {

    const data = this.props.currencies;

    console.log(data);

    // this.createTable(data);


  } // END componentDidMount


  createTable = (data) => {

    const table = document.createElement('table');
    
    // Create headers.
    const headerRow = table.insertRow();
    
    // Empty cell for currency column.
    headerRow.insertCell();
    
    // Get the keys of the first item.
    Object.keys(Object.values(data)[0]).forEach(key => {
      const header = document.createElement('th');
      header.textContent = key;
      headerRow.append(header);
    });

    // Create rows of data.
    Object.entries(data).forEach(([ currency, values ]) => {
      const row = table.insertRow();
      const header = document.createElement('th');
      header.textContent = currency;
      row.append(header);

      Object.values(values).forEach(value => {
        row.insertCell().textContent = value;
      });
    });

    document.querySelector('#table').append(table);
  };

  render() {
    return (
      <div id="table"></div>
    )
  }
}

export default CurrencyData;

Upvotes: 0

Views: 96

Answers (2)

bakar_dev
bakar_dev

Reputation: 996

Add this condition to your App.js, because when the currency component first time renders it receives an empty {} object, which leads to error. Check CodeSandBox

{Object.keys(this.state.currencies).length > 0 ? <CurrencyData currencies={this.state.currencies} /> : "loading"}
    

Upvotes: 1

Guruparan Giritharan
Guruparan Giritharan

Reputation: 16364

You are having an empty object as the default value for currencies

so here if an empty object is passed the above error would be thrown as its undefined

Object.keys(Object.values(data)[0]);

So you should have a check before doing this like data!==null and data.length>0

And you should set the default value of currencies to an empty array as you are setting an array to it.

Upvotes: 1

Related Questions