DEV Community

Cover image for Let's build a Meme app with react in 1 hour
Sadeedpv🥇
Sadeedpv🥇

Posted on

Let's build a Meme app with react in 1 hour

Hello, today we are gonna build a Meme app with react.js. Here is the link to the github repo and here is the link to the website. This app is build with the Meme Api.

This is a pretty simple app and this tutorial is for absolute beginners. Okay let's start by creating the react app with the command

npx create-react-app <Appname>
Enter fullscreen mode Exit fullscreen mode

And let's clean up the folders and start fresh. Run the command to start the app

npm start
Enter fullscreen mode Exit fullscreen mode

If there are no errors, you should see a blank screen. In the 'src' folder, let's create a new folder called 'components' and modify your app.js file like this.

import Header from "./components/Header";
import Post from "./components/Post";

function App() {
  return (
    <>
    <Header />
    <Post />
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Okay, here we declare two components called Header and Post(which we haven't made yet). Now come to the components folder that we created and create two new files 'Header.js' and 'Post.js'. Our folder structure should look like this:

Folder structure

Our header component is quite simple, we have a title and a subtitle.

function Header() {
  return (
    <div className='header'>
        <h1>Read unlimited Memes <span>&#128512;</span></h1>
        <h3>Scroll down &#8595;</h3>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Here '&#128512' is the html entity for the emoji 😃 and '&#8595' is the html entity for ↓.

Here is a tip. If you want to create a function component in vs code, you could use the shorthand 'rfce' by installing the reactjs code snippets extension. You can learn more about such shortcuts on the internet.

Now let's add some styling to the code.

.header {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 40px;
}
Enter fullscreen mode Exit fullscreen mode

Now our header component should look like this:

Header component
You can make your own changes to the styling or you can keep it simple and minimal.

Now before we get into Post.js, we need to install axios and react-icons (it's not necessary).

npm install axios, react-icons
Enter fullscreen mode Exit fullscreen mode

Inside Post.js, we will declare two components: Post and Card. Post component should look like this. (Don't forget to import the css files and axios)

function Post() {
    const [state, sestate] = React.useState();

    useEffect(() =>{
        axios.get(`https://meme-api.herokuapp.com/gimme/50`).then(response => {
            sestate(response.data.memes);
        }).catch(err => {
console.log(err)})
    }, [])

  return (
    <div className='post'>
        {state && state.map((meme, index) => {
            return <Card key={index} url={meme.url} name={meme.author}/>
        })}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Before we jump into the next section, you need to have a good understanding of useState and useEffect. So please do visit those links.

Here, inside the useEffect (to perform some actions before rendering a component), we set a state for the data returned by the API call. If you look at the api, you could see the that the url returns the URL for the image and 'author' give us the one who posted the meme. We send those data to the Card component as props.

Now let's create the card component. Here, we could display the data sent by the post component by {props.name} or {props.url}. Don't forget to add the parameter 'props' to the Card component

function Card(props){
    return(
        <div className='card'>
            <div className='frow trow'>
            <div className='name'>{props.name}</div>
            <div><FaEllipsisH style={{marginRight:'20px'}}/></div>
            </div>


            <div className='img'><img src={props.url} alt='Meme'/></div>
            <div className='frow'>
                <div className='lefticons'>
                    <FaHeart className='icon' size={40}/>
                    <FaComment className='icon' size={40}/>
                    <FaPaperPlane className='icon' size={40}/>
                </div>
                <div className='righticons'>
                    <FaBookmark className='icon2' size={40}/>
                </div>
            </div>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Please ignore the horrible classnames I have given, it's just for styling purposes.

Now, we have a working app, but you could only display 50 memes at a time. If you look at the documentation, you could see that maximum number of calls you could make is 50.

axios.get(https://meme-api.herokuapp.com/gimme/50);

Here the 50 at the end represents no of memes required per call.

So we need the app to load more data when the user scrolls till end. So, How do we do that? First we need to modify our current useEffect function we have created.


    useEffect(() =>{

        window.addEventListener('scroll', handleScroll);

        axios.get(`https://meme-api.herokuapp.com/gimme/50`).then(response => {
            sestate(response.data.memes);
        }).catch(err => {
            console.log(err);
        })

        return () => window.removeEventListener('scroll', handleScroll);

    }, [])
Enter fullscreen mode Exit fullscreen mode

We haven't created a function called 'hanldeScroll' yet, let's keep that for later. Then, we will create another useEffect function and declare another state, and will set it to false initially.

const [fetch, setfetch] = React.useState(false);
Enter fullscreen mode Exit fullscreen mode
    useEffect(() =>{
        if (fetch){
            axios.get(`https://meme-api.herokuapp.com/gimme/50`).then(response => {
                sestate(prevState => [...prevState, ...response.data.memes]);
            })

    }, [fetch])
Enter fullscreen mode Exit fullscreen mode

This useEffect will only be called when the state of the 'fetch' changes. The app won't work as we expected yet. but that's where the 'handleScroll' function comes in.

    function handleScroll() {
        if (window.innerHeight + document.documentElement.scrollTop +2 >= document.scrollingElement.scrollHeight) {
            // Do load more content here!
            setfetch(true)
        }
      }
Enter fullscreen mode Exit fullscreen mode

What we are doing here is changing the state of 'fetch' to true when the user reaches the end of the window. When the state of the fetch changes, the above useEffect gets called and thus we can load more data to the state.

We are not yet finished yet. Now we need some mechanism to change the state to false. so we use the settimeout function.

useEffect(() =>{
    if (fetch){
        axios.get(`https://meme-api.herokuapp.com/gimme/50`).then(response => {
            sestate(prevState => [...prevState, ...response.data.memes]);
        })
        setTimeout(() =>{
            setfetch(false);
        },2000)            
    }

}, [fetch])
Enter fullscreen mode Exit fullscreen mode

I guess that's it. I have tried my absolute best to explain things. Please do give your feedback so that I could improve more. Thank you! Have a good day!

Top comments (0)