Please develop a simple web page that contains a button, that when clicked, makes a call to a REST endpoint to retrieve data. Once the data is retrieved, the page should display the data on the page in a table or div or span, etc.
- You can use either javascript or React
- The page just needs to run on a local environment (no need to deploy it to a hosted server)
- The page should not reload to display the data - it should be injected directly on the page after the call returns
- You can use an REST API to get the data. Here are some random free ones you can call.
- You're welcome to write your own REST endpoint, but that is not required.
- Apply some css styling to the button page. We're not looking for a master piece, but rather some rudimentary styling.
- This encompasses Pokemon API assignment.
- This repo is linked to interview-challenges project
- Normally for this course, I avoid shorthand syntax to avoid unnecessary confusion from small syntax variations. However, in this example I want to write code that won't make the potential employer wonder if I only know long-form syntax.
- Click to fetch from API and set state to the fetched data to update the page without a page reload.
- Teach how to approach a simple interview challenge like this one.
- Show discrete, descriptive, and frequent commits.
- Start simple and clean, then refactor and polish.
npx create-react-app fetch-buttongit commit -m "init react app"
- Paste https://jsonplaceholder.typicode.com/users into address bar to see the data.
- Let's start by displaying the name of each user.
- Let's use
fetchinstead of installing a package likeaxiossince this a simple project and we want to show that we don't need to rely on packages to do everything, even small things. - However,
fetchonly triggers the.catchwhen there is a network error.axiostriggers the.catchwhenever the request is not successful in the successful HTTP status numerical range.- So we need to make sure to trigger the
.catchwheneverfetchreceives an unsuccessful status code. - How would you have known this difference? Either by running into the problem and noticing it behaves differently and then investigating, or by preparation from reading documentation on how
fetchworks and googlinghandle errors with fetch javascript.
- So we need to make sure to trigger the
importReact,{useState}from"react";functionApp(){const[users,setUsers]=useState(null);const[error,setError]=useState(null);consthandleFetchClick=(_e)=>{// fetch("http://httpstat.us/500") // error testfetch("https://jsonplaceholder.typicode.com/users").then((res)=>{if(!res.ok){thrownewError(res.statusText);}returnres.json();}).then((resData)=>{// Clear any previous errors so they aren't still displayed.setErrors(null);setData(resData);}).catch((err)=>setError(err));};constfetchBtnText=users ? "Refresh Users" : "Fetch Users";// If this were a larger project, I would use a CSS-in-js library.return(<divstyle={{maxWidth: "85%",margin: "0 auto"}}><buttononClick={handleFetchClick}style={{padding: 5,fontSize: 22,marginTop: "2rem",marginBottom: "2rem",}}>{fetchBtnText}</button>{users&&users.map((user)=><pkey={user.id}>{user.name}</p>)}{error&&<pstyle={{color: "red"}}>{error.message}</p>}</div>);}exportdefaultApp;- At this point, we have already completed the Pokemon API assignment and the requirements for this challenge except for styling.
- However, it would be good to demonstrate more knowledge of react.
constUsersTable=({ users })=>{if(!users){returnnull;}return(<table><thead><tr><th>#</th><th>Name</th><th>Username</th><th>Email</th><th>Address</th></tr></thead><tbody>{users.map(({ id, name, username, email, address },i)=>(<trkey={id}><td>{i+1}</td><td>{name}</td><td>{username}</td><td>{email}</td><td></td></tr>))}</tbody></table>);};exportdefaultUsersTable;git commit -m "display basic users table"
- Demonstrate we know more than just inline styles.
.striped {
border-collapse: collapse;
border-spacing:0;
width:100%;
border:1px solid #ddd;
}
.stripedth,td {
text-align: left;
padding:16px;
}
.stripedtr:nth-child(even) {
background-color:#f2f2f2;
}
.stripedthead {
border-bottom:1px solid lightgray;
}import{striped}from"./UsersTable.module.css";<tableclassName={striped}>git commit -m "add table styles"
constAddress=({address: { suite, street, city, zipcode }})=>(<span>{suite}{street}, {city}{zipcode}</span>);exportdefaultAddress;importAddressfrom"./Address";<td><Addressaddress={address}/></td>;git commit -m "create Address component
- Loading starts when the request is being sent and it ends when the response comes back or there is an error.
const[loading,setLoading]=useState(false);consthandleFetchClick=(_e)=>{setLoading(true);- Add a
.finallyto stop loading whether the.thenor the.catchhappens.
.finally(()=>{// Loading stops both on success and fail.setLoading(false);});- Conditionally render a loading gif instead of the button
{loading ? (<imgsrc="https://i.gifer.com/ZZ5H.gif"alt="loading"width="40px"height="40px"/>) : (<buttononClick={handleFetchClick}style={{padding: 5,fontSize: 22,marginTop: "2rem",marginBottom: "2rem",}}>{fetchBtnText}</button>);}We could also create a loading component if it needed to be reused.
git commit -m "added loading spinner"
onClickof a row, display full user info above table as a different style inApp.jsby passing a callback from parent to child to handle the child to parent communication.
const[selectedUser,setSelectedUser]=useState(null);{selectedUser&&<h2>{selectedUser.name}</h2>;}<UsersTableusers={users}setSelectedUser={setSelectedUser}/>;constUsersTable=({ users, setSelectedUser })=>{};<trkey={id}onClick={(_e)=>setSelectedUser(users[i])}>importAddressfrom"./Address";constUserCard=({ user })=>{if(!user){returnnull;}const{ name, username, email, address, phone }=user;return(<divstyle={{borderRadius: 5,padding: "1px 30px 1px 30px",margin: "0 auto 2em auto",width: "20%",boxShadow: "rgba(0, 0, 0, 0.16) 0px 1px 4px",backgroundColor: "aliceblue",}}><h2>{name}</h2><small>{username}</small><p>{email}</p><Addressaddress={address}/><p>{phone}</p></div>);};exportdefaultUserCard;<UserCarduser={selectedUser}/><UsersTableusers={users}setSelectedUser={setSelectedUser}/>- In the
.thensetSelectedUser(null);. git commit -m "show user card on click"git push
- Showing knowledge of a CSS in JS library such as styled components would be a nice extra.
- Another interview challenge required styled components.