So we managed to post a new tweet in the previous chapter – great! However, that action is pretty pointless if you cannot see the tweet anywhere afterwards...
Creating the profile page
Let's start by creating the user's profile page, and display all of the user's tweets there.
The first thing we want to do is create a
getUserIdFromUsername function in our frontend, since we'll be fetching a user based on the username in the browser URL (e.g. my user profile would be found at
With this, we can create a new basic profile page showing the user's avatar, name and bio. We'll name the file
Now, in your browser, go to the URL
localhost:3000/profile?u=tristan (or whatever username you picked) and you should see something similar to this:
Rendering the tweets
Now we want to display the tweets on the page as well. The first thing we'll need is a
getTweetIdsFromUser function in our frontend:
We'll start by simply logging the tweet IDs in our profile page to make sure that they were fetched correctly.
Next, we'll create components to actually render these tweets. First, we'll need a component for a single tweet. Let's check our reference mockups so that we know how to design it:
One obvious thing that we're still missing is the user data for every tweet. In the info we logged, we can only see the user's ID – but we also need their username and avatar at the very least!
To fix that, we'll create a new function called
loadTweetsFromTweetPromises which loops through every tweet and fetches the user info for it (this could probably be made more efficient using a state library like Redux, but it's good enough for this project).
Now we use this function in the
profile.js and log the new data:
In the UI, we also want to display the timestamp relatively to the current time (e.g. "2 hours ago"), so we'll download the
react-moment library for that.
Now that we have everything that we need, let's build that
We also want to have a wrapping
TweetList component which loops through the list of tweets and renders every one of them as a
Finally, we make some changes to our profile page, so that the tweets are added to the component state and the
TweetList is rendered in the middle of the page.
Refresh the page and you should see your rendered tweet on the page!
Preparing the contract for a news feed
The final feature that we need in our DApp is the ability to display all the latest tweets in some kind of "news feed".
In our current
TweetStorage contract though, there's no way for us to fetch a list of all the posted tweets, since we're storing them all as a mapping and not an array.
A solution to this problem would be to rewrite our contract, and store all the tweet IDs in an array. We would then have to push a new ID into the array every time a tweet is created.
Let's also write a short test to make sure that we can get an ID from this array by providing an index:
Before we move on to the frontend, let's remember that a news feed always shows the latest entries first, so we actually want to be able to fetch the array's data in a reverse order.
In order to be able to do this, we need to know what the last index of the array is, and the only way to know that is to know the array's length. Therefore we should add a
getNumTweets getter function to our storage contract, which simply returns the size of the list as an integer.
Rendering our news feed
Once again, we need to re-run
npm run dev in order for the updated contracts to be compiled and redeployed.
Note that you'll have to recreate your user and your tweets again after doing this.
We now want to create a
getLatestTweetIds function for our frontend. We're going to try to build it in a extensible way using
page parameters, so that we can use infinite scrolling in a future version of our DApp (in case the list of tweets grows to be really long).
By default, we will start with the 5 latest tweets.
Using this, we can now create our final page,
home.js, and render the list of tweets in it.
Finally, we want to redirect to this new page if the user visits
/ and is logged in.
Congratulations! You should now have a pretty well-functioning DApp! In the next chapter, we're going to see how we can deploy it to one of Ethereum's public test networks.