amishpanda
amishpanda

Reputation: 13

React - Empty Array When Rendering JSON Data

Why is an empty array created when rendering this JSON array? See attached screenshot I assume the constructor is just initiating it with a null value and filling it at a later point.

New to Javascript + React and just want to make sure I am understanding what is happening. I will also accept critique on the garbage code that is below. Codepen link

class Jobs extends React.Component {
  render() {
    const jobs = this.props.jobs;
    console.log(jobs);
    const formattedJobs = jobs.map((job) =>
      <ul key={job.id}> 
        <div class="company">{job.company_name}</div>
        <div class="title">{job.title}</div>
      </ul>
    );
    return(
      <div>{formattedJobs}</div>
    );
  }
}

class App extends React.Component {
  constructor() {
    super();
    this.state={
      jobs:[]
    }
  var myUrl = "https://codepen.io/jobs.json";
  fetch(myUrl)
    .then((response) => response.json())
    .then((json) => this.setState({jobs: json.jobs}));
  }

  render() {
    return (
    <div className="app">
      <div className="header">
        <h1 id="header-title">Job Postings</h1>
      </div>
      <div className="content">
        <Jobs jobs={this.state.jobs}/>
      </div>
    </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Upvotes: 1

Views: 3373

Answers (3)

Krzysztof Safjanowski
Krzysztof Safjanowski

Reputation: 7438

Jobs component

  • always be nice for default props - component can / will render before fetch returns response
  • replace class with className as first one is restricted word in JSX
  • ul can only contains li childs - not div
  • nice for use key property when you iterate over collection

App component

  • there is place for suppor unexpected response, you can set new state like error and support it
  • please consider with component is responsible to support errors and spinners- App or Jobs

Ract application

class Jobs extends React.Component {
  render() {
    const { jobs } = this.props;
    const formattedJobs = jobs.map(job =>
      <ul key={job.id}>
        <li className="company">{job.company_name}</li>
        <li className="title">{job.title}</li>
      </ul>
    );

    return <div>{formattedJobs}</div>;
  }
}

Jobs.defaultProps = {
  jobs: []
};

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      jobs: []
    };
  }

  componentDidMount() {
    fetch("https://codepen.io/jobs.json")
      .then(response => response.json())
      .then(response => {
        if (!Array.isArray(response.jobs)) {
          throw new Error(
            `Expected response but got ${JSON.stringify(response.jobs)}`
          );
        } else {
          return response.jobs;
        }
      })
      .then(jobs => this.setState({ jobs }));
  }

  render() {
    return (
      <div className="app">
        <div className="header">
          <h1 id="header-title">Job Postings</h1>
        </div>
        <div className="content">
          <Jobs jobs={this.state.jobs} />
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

Upvotes: 1

Vikram Saini
Vikram Saini

Reputation: 2771

always use fetch statements in ComponentDidMount as it is called just after your component is rendered for the very first time

ComponentDidMount {
 fetch(myUrl)
    .then((response) => response.json())
    .then((json) => this.setState({jobs: json.jobs}));
}

Upvotes: 1

nicowernli
nicowernli

Reputation: 3348

You are getting the jobs from an ajax request wich is async. Thats why the initial value is an empty array.

App.render is executed before your ajax request is finished and thats why you are not givin any job to the Jobs component. Once the ajax is finished, the jobs array is filled with the results and sendeded to the Jobs component to render the results of that ajax request.

Upvotes: 1

Related Questions