This is the real purpose for react context

Поделиться
HTML-код
  • Опубликовано: 29 дек 2023
  • 📘 T3 Stack Tutorial: 1017897100294.gumroad.com/l/j...
    🤖 SaaS I'm Building: www.icongeneratorai.com/
    ▶️ Generate Chapters: ytchaptersgenerator.com/
    💬 Discord: / discord
    🔔 Newsletter: newsletter.webdevcody.com/
    📁 GitHub: github.com/webdevcody
    📺 Twitch: / webdevcody
    🤖 Website: webdevcody.com
    🐦 Twitter: / webdevcody

Комментарии • 71

  • @amir-ziaei
    @amir-ziaei 7 месяцев назад +47

    A better way is to just let the http call happen during the test but instead return a mocked response at network level. MSW makes this very easy. Not only you get more confidence (because your fetching logic also gets tested), but also doesn't make your code more verbose and sacrifice the runtime performance because of additional wrappers.

  • @moosa3956
    @moosa3956 7 месяцев назад +4

    I was super confused until you showed the test implementation and then everything clicked
    Nice

  • @isaackoz
    @isaackoz 7 месяцев назад +4

    The best part about this is you only have to define the types once. With prop drilling you either have to define them in each file or import them, but with context TS would infer them automatically.

  • @ProfessorThock
    @ProfessorThock 7 месяцев назад +2

    Yeah this is exactly what I use context for it’s great. You can create a theme context, an api context (maybe several), a state context, etc. Very useful

  • @gavinlindridge
    @gavinlindridge 7 месяцев назад +5

    You have an awesome habit of crearing just the right content at the tight time for me 👍
    Been switching my current employers codebases to use a similar pattern and this has validated i wasnt going off piest.

  • @richardantao3249
    @richardantao3249 7 месяцев назад +9

    The same can be achieved with props. I think having multiple contexts for stubbing would be just as messy as prop drilling

  • @andreas.111
    @andreas.111 7 месяцев назад

    This definitely helped me understand context a lot more than just keeping track of state, really useful!

  • @ltsSmitty
    @ltsSmitty 7 месяцев назад +1

    Great example. I've never really known how this was implemented so that's great to see

  • @eduardstefan6833
    @eduardstefan6833 7 месяцев назад +19

    Great video. As someone who has never done proper tests I always assumed that providers would be harder to test but it's actually even easier.
    Also a small tip for everyone: You can throw Error if value is null inside the useDataMuseApiContext before returning so that you don't need to always check for null in every component where you're calling the hook.
    export function useDataMuseApiContext(){
    const value = useContext(DataMuseApiContext)
    if (!value) throw new Error('You forgot to pass a value to the provider or you're using the context outside of DataMuseApiProvider')
    return value //

    • @rand0mtv660
      @rand0mtv660 7 месяцев назад

      Yeah, creating a custom hook for every custom provider you have is an awesome pattern. I use it all the time because I just want to get the thing I'm after, I don't care if the underlying implementation is React Context or anything else. I just want to use for example "useCurrentUser()" and not worry about where this user is coming from.

    • @WebDevCody
      @WebDevCody  7 месяцев назад +1

      Very cool! I’ve seen that in a couple of libraries but I’ve never looked into it 😅

    • @pedhead
      @pedhead 7 месяцев назад

      This is helpful if your teammates forget to wrap acomponent in a provider. Also makes it easier to change the context, all components can use the same custom hook. @@WebDevCody
      ```
      import { useMediaQuery } from "@mui/material"
      import { useEffect, useState, createContext } from "react"
      const ModeContext = createContext()
      const ModeProvider = ({ children }) => {
      const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)")
      const [mode, setMode] = useState(prefersDarkMode ? "dark" : "light")
      const [mounted, setMounted] = useState(false)
      useEffect(() => {
      setMode(prefersDarkMode ? "dark" : "light")
      setMounted(true)
      }, [prefersDarkMode])
      const toggleMode = () => {
      setMode(mode === "dark" ? "light" : "dark")
      }
      const value = {
      mode,
      toggleMode,
      }
      return (

      {mounted && children}

      )
      }
      function useModeContext(){
      const modeContext = useContext(ModeContext)
      if(modeContext === undefined){
      throw new Error("mode context must be called within a ModeContextProvider")
      }
      return modeContext
      }
      export { ModeProvider, useModeContext}
      ```
      An added benefit is you don't need to export the entire context anymore. Also abstracts away the implementation details in your components!

    • @gavinlindridge
      @gavinlindridge 7 месяцев назад +1

      Yep love using this pattern 👍

  • @chiubaca
    @chiubaca 7 месяцев назад +1

    Nice advice for if you're working with storybook too!

  • @nhwhn
    @nhwhn 7 месяцев назад

    Happy new year.

  • @m_yoda
    @m_yoda 7 месяцев назад +1

    Nest.JS forces to use the approach of dependencies injections and it is very comfortable. You don't need to mock "import" but you can just define what you need and pass to modules.

    • @WebDevCody
      @WebDevCody  7 месяцев назад

      Sounds nice for an api

  • @qasimqadrii
    @qasimqadrii 6 месяцев назад

    Love the way you explain! ♥

  • @jacobhuiet4217
    @jacobhuiet4217 6 месяцев назад +1

    Interesting idea. I can’t tell if I like it yet but my intuition is telling me to avoid for some reason

  • @alirezvani9149
    @alirezvani9149 7 месяцев назад +3

    I wish they add a cleaner look for context api, something more elegant like redux api. I really hate wrapping the root element 20 times to add the contexts I want

    • @N8X4TE
      @N8X4TE 7 месяцев назад

      What is wrong with wrapping root element 20 times with providers?

    • @alirezvani9149
      @alirezvani9149 7 месяцев назад

      ​@@N8X4TEIt gets hard to maintain real quick

    • @carljung4733
      @carljung4733 7 месяцев назад +4

      Create a Providers component with all your providers and pass root elements as children, cleans up root file.

  • @fitzsimonsdev
    @fitzsimonsdev 7 месяцев назад +3

    I once tried to explain this at a job where I was contracting. They refused to believe you could do this even though I literally showed them.
    Happily I'm somewhere better now.

  • @SeibertSwirl
    @SeibertSwirl 7 месяцев назад

    Good job love!

  • @eleah2665
    @eleah2665 7 месяцев назад

    Very good. Thanks.

  • @ankitpradhan4183
    @ankitpradhan4183 7 месяцев назад +2

    well even passing props or argument is a kind of dependency injection.
    you cant say"real purpose". It would be the same purpose as of props i.e. to inject some dependency to component.
    The use of context is to have stuffs that essentially needs to be shared among all the sibling component. Thats it. Dont try to complicate things by bringing in words like DI.
    Even Functions are DI. some functions that are hard to be tested can be extracted out of hook or component passing dependencies and test it.
    anything you want to share among siblings like some sidebar state as example, modal providers, api calls etc etc etc.
    I will give you props to show one of most realistic example to use this.
    But beginners, be careful to properly memoize your context values because it can cause your whole shit to re render if not done properly😢

    • @ProfessorThock
      @ProfessorThock 7 месяцев назад

      I like that he’s showing off the context api because way too many people do prop drilling or jump all the way to redux and stuff when they can easily make their own bespoke lightweight contexts very easily.
      But yeah when he said it’s dependency injection I immediately was like “wait what… props are also dependency injection” which made it sound like he was just trying to use a complicated word that he didn’t know but tbf I think it is more decoupled than props so I can see what he was thinking and seems like he just quickly threw together a video to show this off

  • @rafavieceli
    @rafavieceli 7 месяцев назад

    And you can nest the same provider, I solved a problem where I had projects and subprojects with different permissions, so project had its contexts, and each subproject (as a child) has its own context as well.

  • @pintae8681
    @pintae8681 7 месяцев назад

    Great content!

  • @omarcodes5181
    @omarcodes5181 7 месяцев назад

    Great video

  • @code-island
    @code-island 6 месяцев назад

    Really good content

  • @javierperezmarin6039
    @javierperezmarin6039 7 месяцев назад +1

    I use this exacly but with react query

  • @didier2839
    @didier2839 7 месяцев назад

    This is good💥

  • @ayoubkassi4103
    @ayoubkassi4103 7 месяцев назад

    Cool video

  • @user-ik7rp8qz5g
    @user-ik7rp8qz5g 7 месяцев назад +1

    I watched it twice, but I stop understanding from the moment you create context provider. Is there easier explanation of what we are trying to achieve by doing this and how/why exactly it is better than not doing it?

    • @WebDevCody
      @WebDevCody  7 месяцев назад

      It’s basically a global store for dependencies that all your react components can load in when needed

    • @hypeerj
      @hypeerj 7 месяцев назад +1

      Imagine you are trying to test this component. Without Dependency Injection or intercepting the API call the test case would try to fetch you API which is something you really don't want to do. Instead, via Dependency Injection you can replace the real fetching with returning mocked response

    • @user-ri1vc4qv8j
      @user-ri1vc4qv8j 6 месяцев назад

      ​@@hypeerjgreat explanation!

    • @hypeerj
      @hypeerj 6 месяцев назад

      @@user-ri1vc4qv8j somehow I forgot about mocking functions ;b, so this is 3rd option

  • @jacobhuiet4217
    @jacobhuiet4217 6 месяцев назад

    From my understanding, this would move all fetches to the client side right? At that point you lose the ability to do fetching on the server with this paradigm. If this was to be used at the top level you’d probably be better off using tanstack query to get all the other benefits of that (loading states, error handling, caching)

  • @AdityaSharma-lb9bx
    @AdityaSharma-lb9bx 7 месяцев назад

    Didn't understand much. I'll watch it again

  • @JH-bb8in
    @JH-bb8in 7 месяцев назад +2

    Yeah but if you do this, won't you have to wrap your app.js with a whole bunch of nested providers?

    • @yousefkhalil7540
      @yousefkhalil7540 7 месяцев назад +1

      You could use one context provider at the root where you inject an instance of every class, than you have custom hook that extracts only the class instance you really need. You could also use multiple contexts at different part of your app, each context provides a specific class instances.

    • @veedjohnson
      @veedjohnson 7 месяцев назад

      @@yousefkhalil7540do you have a codebase that shows this?

    • @N8X4TE
      @N8X4TE 7 месяцев назад

      What is wrong with the whole bunch of nested providers?

    • @veedjohnson
      @veedjohnson 7 месяцев назад

      @@N8X4TE ugly looking code, sometimes you might have to rearrange your nesting a couple of times

    • @doc8527
      @doc8527 7 месяцев назад

      ​@@yousefkhalil7540 be aware of that if you only need a function from particular provider or instance, you will load the entire chunk of codes for a single function, which could unnecessary bloat your bundle size comparing to the import individually. One is minor, but if every single package is written in this way. It will be quickly bloated. Tree shaking might not work in this case as its inside the class. There is tradeoff and side effect if the instance modify something unexpectedly. But the side effect could be a feature and very handy if you want to modify some internal functionality during the runtime. The auto interface hinting is also very handy as a whole.

  • @anilsonix
    @anilsonix 7 месяцев назад

    Could you make a video react project structure like feature slice design

  • @guitar2935
    @guitar2935 7 месяцев назад

    Maybe I'm just too green on React and not seeing where I could apply this but this specific example feels overly verbose. If the problem is easily swapping dependencies for testing purposes it would make more sense to me to just have a separate custom hook for testing than wrapping everything in a bunch of providers. Regardless this was a great rundown of what you can achieve with context!

    • @WebDevCody
      @WebDevCody  7 месяцев назад +1

      A custom hook would work ok, but I’m not a fan of having your entire test suite coupled to jest spy. Because in 3 years when jest is no longer cool and something faster such as vitest comes out, now you have to refactor a ton of code to switch compared to doing the dependency injection with your own approach.

  • @kevinclark1783
    @kevinclark1783 7 месяцев назад

    Eh, it’s great till you have a ton of stuff on the context to mock. To me, a simple custom hook is the best, because it’s simple to mock with Jest spies and you can give each test a resolved value easily. But a nice explanation, thank you.

    • @jacobhuiet4217
      @jacobhuiet4217 6 месяцев назад +1

      You could have a default object for mocking that mirrors what the type was and then override for your use case 🤔. I’m not sure it’s a good idea, I’m still trying to figure out if I like what he proposed

  • @favanzzo
    @favanzzo 7 месяцев назад

    vscode theme?

  • @therealsharat
    @therealsharat 7 месяцев назад

    I am not sure if making the layouts page a client component is a good practice

    • @WebDevCody
      @WebDevCody  7 месяцев назад

      Is that what you got from this video?

    • @therealsharat
      @therealsharat 7 месяцев назад

      @@WebDevCody not at all, the video gave a nice use case of context, I just personally prefer setting contexts in completely different files rather than in layout
      Just so that the new viewers who watch this channel don't get the wrong idea on how to use context

    • @WebDevCody
      @WebDevCody  7 месяцев назад +1

      @@therealsharat usually I make a separate file called providers and I use client at the top of that file.

  • @markup100
    @markup100 7 месяцев назад +4

    Not the best example. It feels like a backend/mobile dev is trying to teach you frontend development. Things can be much different on this side. Keep in mind about overhead you are adding by creating contexts (performance, when you update state your whole tree is rerendered, doesn't work with RSC, etc.), and you have to have a very, very good reason for using them

  • @edxmo2921
    @edxmo2921 6 месяцев назад

    Isn't It a kind of strategy pattern? Wyt?

  • @im7254
    @im7254 7 месяцев назад

    class lol

  • @parlor3115
    @parlor3115 7 месяцев назад

    Idk about DI. DI automatically provides dependencies based on parameter types and supports recursive dependency resolution. Context is just global storage. Agreed on the benefits, though.

    • @WebDevCody
      @WebDevCody  7 месяцев назад

      There are many types of dependency injection approaches. Having it be automatic isn’t the reason it’s dependency injection. Google “what types of dependency injection are there”

    • @parlor3115
      @parlor3115 7 месяцев назад

      @@WebDevCody On a further read, this is indeed DI. Automatic injection and recursive resolution are not necessary for it to be considered so. I guess I'm used to C# and Symfony working that way.

  • @claus4tw
    @claus4tw 7 месяцев назад

    I don’t know. You really should not test the fetch. Test the function That mutates the response

    • @WebDevCody
      @WebDevCody  7 месяцев назад

      I’m not testing the fetch

  • @moodyhamoudi
    @moodyhamoudi 7 месяцев назад +3

    not a piano vid unsubbed

  • @noahginsburg6140
    @noahginsburg6140 4 месяца назад

    second watch on this video. great content.

  • @ayushjain7023
    @ayushjain7023 7 месяцев назад +1

    React context is not for maintaining server states 😐 use react query instead plz, title of the video is misleading, it’s a first time I got to disagree with you

    • @WebDevCody
      @WebDevCody  7 месяцев назад +1

      What does server states have to do with my video? The main idea was related to abstraction and dependencies. You can still use react query but pass the api interface methods into your react query calls