Lesson 15

Displaying tweets

1

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 /profile?u=tristan.

client/web3/users.js

With this, we can create a new basic profile page showing the user's avatar, name and bio. We'll name the file profile.js:

client/pages/profile.js

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:

client/web3/tweets.js

We'll start by simply logging the tweet IDs in our profile page to make sure that they were fetched correctly.

client/pages/profile.js

Refresh the page and you'll hopefully see the tweet that you posted earlier in your JavaScript console:


There it is!


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).

client/web3/tweets.js

Now we use this function in the profile.js and log the new data:

client/pages/profile.js


You should now see a new "user" field in your array of tweets!


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 Tweet-component!

client/components/Tweet.js

We also want to have a wrapping TweetList component which loops through the list of tweets and renders every one of them as a Tweet component:

client/components/TweetList.js

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.

client/pages/profile.js

Refresh the page and you should see your rendered tweet on the page!

Awesome!

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".


A mockup of our 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.

contracts/tweets/TweetStorage.sol

Let's also write a short test to make sure that we can get an ID from this array by providing an index:

test/integration/tweets.js



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.

contracts/tweets/TweetStorage.sol

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 amount and 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.

client/web3/tweets.js

Using this, we can now create our final page, home.js, and render the list of tweets in it.

client/pages/home.js

Finally, we want to redirect to this new page if the user visits / and is logged in.

client/pages/index.js


And there you have it!


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.

Comments

icon

Be the first to comment!