SWR

React Hooks for Data Fetching (by vercel)

SWR Alternatives

Similar projects and alternatives to SWR

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a better SWR alternative or higher similarity.

SWR reviews and mentions

Posts with mentions or reviews of SWR. We have used some of these posts to build our list of alternatives and similar projects. The last one was on 2022-11-29.
  • 📚 RTK Query Tutorial (CRUD)
    3 projects | dev.to | 29 Nov 2022
    Maybe, some of you already heard about React Query or SWR. I believe those state management package have the same concept with the RTK Query. However, a winning point about RTK query is all in one with Redux. If you are using Redux, so it's a free optional feature without installing a new package.
  • Build a Jamstack Blog with Xata and Cloudinary
    3 projects | dev.to | 23 Nov 2022
    import { useState, useEffect } from 'react' import { useRouter } from 'next/router' import { Button, Textarea, Input, FormControl, FormLabel, Container, Text, Spacer, Icon, Link, Spinner, Alert, AlertDescription, AlertIcon, AlertTitle } from '@chakra-ui/react' import { FaGithub } from 'react-icons/fa' import { toast } from 'react-toastify' import generateSocialImage from '../../components/GenerateImg' import useSWR from 'swr' const fetcher = (...args) => fetch(...args).then((res) => res.json()) const UpdatePost = () => { const [title, setTitle] = useState(''); const [body, setBody] = useState(''); const [tags, setTags] = useState(''); const router = useRouter(); const { id } = router.query; //Get data from xata db const { data, error } = useSWR(`/api/post?id=${id}`, fetcher) if (error) return ( Error! Failed to Load. ) if (!data) return // store data in state const res = data.post; // handle form submit const handleSubmit = async () => { //Convert string tags to array const newTags = tags || res.tags.toString(); console.log(newTags) // Reducing number of accepted tags to 4 if user inputs more const tagArr = newTags.split(/[, ]+/); let tags_new; if (tagArr.length >= 4) { tags_new = tagArr.slice(0, 4) } else tags_new = tagArr; console.log(tags_new); //Generate social card with cloudinary const socialImage = generateSocialImage({ title: title || res.title, tagline: tags_new.map(tag => `#${tag}`).join(' '), cloudName: 'dqwrnan7f', imagePublicID: 'dex/example-black_iifqhm', }); console.log(socialImage); //Make add create request let post = { title: title || res.title, body: body || res.body, image: socialImage, tags: tags_new, } const response = await fetch('/api/update', { method: 'POST', headers: { "Content-Type": "application/json", }, body: JSON.stringify({ post, id }) }) if (response.ok) { toast.success("post updated successfully", { theme: "dark", autoClose: 8000 }) window?.location.replace('/'); } } return ( Blog with Xata and Cloudinary Post Title { setTitle(e.target.value) }} /> Post Tags { setTags(e.target.value) }} /> Post Body { setBody(e.target.value) }} /> handleSubmit()}>Submit ) } export default UpdatePost
    Enter fullscreen mode Exit fullscreen mode

    For our other reusable components AllPosts.js and CreateModal.js, we have:

    AllPost.js

        import NextLink from 'next/link'
        import { Box, Image, Badge, Flex, Spacer, ButtonGroup, Link } from '@chakra-ui/react';
        import { DeleteIcon, EditIcon, ExternalLinkIcon } from '@chakra-ui/icons'
        import { toast } from 'react-toastify'
        import ReactMarkdown from 'react-markdown'
        import remarkGfm from 'remark-gfm'
        const AllPosts = ({ posts }) => {
          const deleteData = async (id) => {
            const { status } = await fetch('/api/delete', {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({ id }),
            })
            if (status === 200) {
              toast.success("post deleted successfully", {
                theme: "dark",
                autoClose: 5000
              })
            }
            window?.location.reload()
          }
          return (
            
    { posts && posts.map((post, index) => { return (
    Tags: {post.tags.length > 0 && post.tags.map((tag, index) => { return ( {(index ? ',' : '') + ' ' + tag} ) })} deleteData(post.id)} mt={1} /> {post.title} {post.body}
    ) }) }
    ) } export default AllPosts
    Enter fullscreen mode Exit fullscreen mode

    CreateModal.js

        import { useState } from 'react'
        import {
            useDisclosure,
            Modal,
            ModalOverlay,
            ModalContent,
            ModalHeader,
            ModalBody,
            ModalCloseButton,
            Button,
            Textarea,
            Input,
            FormControl,
            FormLabel,
        } from '@chakra-ui/react'
        import { toast } from 'react-toastify'
        import generateSocialImage from './GenerateImg'
    
        const PostForm = () => {
            const [title, setTitle] = useState("");
            const [body, setBody] = useState("");
            const [tags, setTags] = useState("");
            //Convert string tags to array
            const newTags = tags;
    
            const handleSubmit = async () => {
                if (title == '' || body == '' || tags == '') {
                    toast.warn("post cannot be empty", {
                        theme: "dark",
                        autoClose: 8000
                    })
                } else {
                    const tagArr = newTags.split(/[, ]+/);
                    let tags_new;
                    if (tagArr.length >= 4) {
                        tags_new = tagArr.slice(0, 4)
                    } else tags_new = tagArr;
                    console.log(tags_new);
                    //Generate social card
                    const socialImage = generateSocialImage({
                        title: title,
                        tagline: tags_new.map(tag => `#${tag}`).join(' '),
                        cloudName: 'dqwrnan7f',
                        imagePublicID: 'dex/example-black_iifqhm',
                    });
                    console.log(socialImage);
                    //Make add create request
                    let posts = {
                        title: title,
                        body: body,
                        image: socialImage,
                        tags: tags_new,
                    }
                    const response = await fetch('/api/create', {
                        method: 'POST',
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify(posts)
                    })
                    if (response.ok) {
                        toast.success("post created successfully", {
                            theme: "dark",
                            autoClose: 8000
                        })
                        window?.location.reload()
                    }
                }
            }
            return (
                <>
                    
                        Post Title
                         { setTitle(e.target.value) }} required />
                    
                    
                        Post Tags
                         { setTags(e.target.value) }} required />
                    
                    
                        Post Body
                         { setBody(e.target.value) }} required />
                    
                     handleSubmit()}>Submit
                >
            )
        }
    
        const CreatePost = () => {
            const { isOpen, onOpen, onClose } = useDisclosure()
            return (
                <>
                    Create Post
                    
                        
                        
                            Modal Title
                            
                            
                                
                            
                        
                    
                >
            )
        }
        export default CreatePost
    
    Enter fullscreen mode Exit fullscreen mode

    We used our generateSocialImage Cloudinary function inside the createModal component and update page to generate a social card. Here is an isolated version:

        //Generate social card
        const socialImage = generateSocialImage({
          title: title,
          tagline: tags_new.map(tag => `#${tag}`).join(' '),
          cloudName: 'dqwrnan7f',
          imagePublicID: 'dex/example-black_iifqhm',
        });
        console.log(socialImage);
    
    Enter fullscreen mode Exit fullscreen mode

    We can see how we passed dynamic data to the function, our public image id, cloudname, title from our blog, and taglines from our blogpost too. Our social card will look like this when the function is executed:

    Our transformed social card - Amazing!

    If you followed up till this point, our application is almost ready! Finally, we will go ahead and add some CSS styles to the default stylesheet file in our project globals.css:

        html,
        body {
          padding: 0;
          margin: 0;
          font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
            Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
        }
        a {
          color: inherit;
          text-decoration: none;
        }
        * {
          box-sizing: border-box;
        }
        @media (prefers-color-scheme: dark) {
          html {
            color-scheme: dark;
          }
          body {
            color: white;
            background: black;
          }
        }
        .main {
          padding: 5rem 0;
          flex: 1;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
        }
        .footer {
          width: 100%;
          height: 100px;
          border-top: 1px solid #eaeaea;
          display: flex;
          justify-content: center;
          align-items: center;
        }
        .footer img {
          margin-left: 0.5rem;
        }
        .footer a {
          display: flex;
          justify-content: center;
          align-items: center;
        }
        .grid {
          display: flex;
          flex-direction: row;
          align-items: center;
          justify-content: center;
          flex-wrap: wrap;
          max-width: 80%;
          margin-top: 3rem;
          margin: auto;
        }
        .card:hover,
        .card:focus,
        .card:active {
          color: #0070f3;
          border-color: #0070f3;
        }
        @media (max-width: 600px) {
          .grid {
            max-width: 100%;
            flex-direction: column;
          }
        }
    
    Enter fullscreen mode Exit fullscreen mode

    We will then run our application using any of these commands to see the finished product.

       # NPM
        npm run dev
    
        # Yarn
        yarn run dev
    
    Enter fullscreen mode Exit fullscreen mode

    Now we have our blog running on Xata and Cloudinary serverless provisions. We can go ahead and improve the user interface, make it more responsive and even add some animations too. We can also host it on services like Netlify, Vercel, and any other client-side hosting platforms we can think of. For this article, we will be deploying to Netlify.

    One easy way to deploy to Netlify is to push our code to Github, connect our Github to Netlify and select the repository that contains our project. We will select the Next.js preset build command and everything will run and deploy automatically with fewer or no configurations. Check this article for more insight on deploying to Netlify.

    Our live link on Netlify is ready.

    Conclusion

    So we were able to learn from this article how we can use Jamstack through Next.js, Cloudinary, Xata, and Chakra UI to build a blog application with CRUD functions without setting up any server. Feel free to comment on what you learned, what we did not cover, possible improvements, and also any questions you might have. I will be glad to take your feedback and answer your questions.

    Resources

    Here are some resources that might be helpful:

    5 projects | dev.to | 7 Nov 2022
    We used SWR to fetch our data because it an easier way to handle fetching data at request time in Next.js. The team behind Next.js has created a React hook for data fetching called SWR. it is highly recommend if you’re fetching data on the client side. It handles caching, revalidation, focus tracking, refetching on interval, and more. Read more about it here.
  • My company doesn't use any state management tool. Is that bad?
    2 projects | reddit.com/r/reactjs | 4 Nov 2022
  • How I Made My Portfolio with Next.js
    14 projects | dev.to | 13 Oct 2022
    First, we need to install swr. SWR is a strategy to first return the data from the cache (stale), then send the fetch request (revalidate), and finally, come up with up-to-date data.
  • How to make infinite scroll with search and sort?
    2 projects | reddit.com/r/webdev | 9 Oct 2022
    On your client, I strongly advise you to use the SWR library It exposes a simple React hook for your React components to send API calls and render your component based on the results Further more, it allows supports you very well with infinite scroll/pagination scenarios (read their docs, they have good examples) It will leave you with implementing a nice list of items, that expands as the user scrolls -- that's it.
  • The Hate around Redux and co?
    3 projects | reddit.com/r/reactjs | 19 Sep 2022
    You have tools like react-query, SWR, and Apollo for that. Turns out, if you use those tools, you pretty much don't need global state management in small-mid-sized projects (if you're ok passing props 2-3 levels deep at times).
  • Which State Management Solution do you use with NextJS?
    2 projects | reddit.com/r/nextjs | 18 Sep 2022
  • I am sick and tired of react-redux. Who has some good alternatives?
    18 projects | reddit.com/r/reactjs | 11 Sep 2022
    (2) cached network/async calls, which is solved by something like swr or React Query
  • State of state management u React-u
    5 projects | reddit.com/r/programiranje | 11 Sep 2022
  • A note from our sponsor - Sonar
    www.sonarsource.com | 29 Nov 2022
    Sonar helps you commit clean code every time. With over 300 unique rules to find JavaScript bugs, code smells & vulnerabilities, Sonar finds the issues while you focus on the work. Learn more →

Stats

Basic SWR repo stats
179
24,675
9.2
5 days ago
Truly a developer’s best friend
Scout APM is great for developers who want to find and fix performance issues in their applications. With Scout, we'll take care of the bugs so you can focus on building great things 🚀.
scoutapm.com