In this React tutorial, we’ll keep building on the React Form from the last tutorial. Now we want to be able to fetch data from an API and work with that data in a meaningful way. To do this we’ll need to make use of an array to manage state at the top-level of the application in the App component. We’ll then set up a couple of other components and share state with them via the props object. React will update the UI automatically as we add new data objects to our state array. Let’s see how to build this out now.
User Data Input
We already have a Form set up so that a user can enter a company name, then click go. At that point, an API request is made to the Github rest API, and we get the data back. How can we tap into that data? That is what we’ll take a look at here. At this point, we have this Form we see here.
Each time a user types in a company name, we get a response back from the API. So the first thing we need is to create an array that will hold the information we get back from the API. That way, each time a new company name is added we can add a response object into the array. This is the companyinfoarray
. In addition, we need a function that will add each object to the array each time the user types information into the form and clicks go. This is the addCompany()
function.
class App extends React.Component {
state = {
companyinfoarray: [],
};
addCompany = (companyinfo) => {
this.setState(prevState => ({
companyinfoarray: [...prevState.companyinfoarray, companyinfo],
}));
};
render() {
return (
<div>
<Form onSubmit={this.addCompany} />
</div>
);
}
}
What we are doing here is to put the companyinfo
on the state of the App component. This object is appended to the array of objects stored in companyinfoarray
on the state. The setState
function helps us here as this is the function that we need to change the state of a React class component. We pass a function to setState() that gives access to the previous state, and what is returned from this function becomes the new state. We can return companyinfoarray
where the spread operator is used to append the new companyinfo
. This is equivalent to doing a concat operation on the companyinfoarray
array. Now we can use React Dev Tools to check if this is working.
Excellent! Each time the user types in a company name and clicks go, we can see in React Dev Tools that the companyinfoarray
is populating correctly. In other words, each time we get a response from the Github api, we store that response object right into the state of the React application.
Creating A Company List Component
Our goal is to display all data objects we are storing in the companyinfoarray
of the state. We can do this by creating a React Component whose main job is to display other components. In other words we need a component that will create a list of components. We can start with this code here.
class CompanyList extends React.Component {
render() {
return (
<div className="companylist">
<span className="companylisttext"><CompanyList /></span>
</div>
);
}
}
We also use just some simple CSS to help with the display of the components on the page.
.companylist {
border: thin solid blue;
padding: 2rem;
margin: 2rem;
display: flex;
flex-direction: column;
}
.companylisttext {
position: relative;
top: -47px;
background: white;
padding: 7px;
width: 106px;
color: blue;
}
This gives us our Form component, and the CompanyList component. The different color outlines just help with the visualization.
Passing State From App Component To CompanyList Component
In the screenshot above note that the CompanyList component is selected in React Dev Tools. In the information pane that shows us that there are no Props associated with that component. Well, we need the CompanyList component to have access to the companyinfoarray
state. That means we need to pass it as a prop.
class App extends React.Component {
state = {
companyinfoarray: [],
};
addCompany = (companyinfo) => {
this.setState(prevState => ({
companyinfoarray: [...prevState.companyinfoarray, companyinfo],
}));
};
render() {
return (
<div>
<Form onSubmit={this.addCompany} />
<CompanyList companyinfoarray={this.state.companyinfoarray} />
</div>
);
}
}
Now when we use React Dev Tools with the CompanyList component highlighted, we can see that the component now has access to the data we need. In fact, when we type to add some new companies to the array, our array immediately updates in the CompanyList component. Very cool!
Single Item Component
We need one more component to make the application work. This will be the Company component and it’s job is to just display one single company. So let’s start with this code here for the Company component.
class Company extends React.Component {
render() {
const p = this.props;
return (
<div className="company">
<span className="companytext"><Company /></span>
<img src={p.avatar_url} />
<div className="companyinfo">
<div>Name: {p.name}</div>
<div>Email: {p.email}</div>
<div>Bio: {p.bio}</div>
<div>Repos: {p.public_repos}</div>
</div>
</div>
);
}
}
Rendering A Component Inside Another Component
So the purpose of the Company component above is so that we can render it out using the CompanyList component. In the highlighted code below we use the map function to run a function against each item in the companyinfoarray
. What this does for us is to render a new Company component inside the CompanyList component each time a new API response is added to the array.
class CompanyList extends React.Component {
render() {
const p = this.props;
return (
<div className="companylist">
<span className="companylisttext"><CompanyList /></span>
{p.companyinfoarray.map(companyinfo => <Company key={companyinfo.id} {...companyinfo}/>)}
</div>
);
}
}
Now we test out the application and can see the different components working together to render the data.