This is the real purpose for react context
Vložit
- čas přidán 29. 12. 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
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.
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.
I was super confused until you showed the test implementation and then everything clicked
Nice
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 //
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.
Very cool! I’ve seen that in a couple of libraries but I’ve never looked into it 😅
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!
Yep love using this pattern 👍
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.
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
This definitely helped me understand context a lot more than just keeping track of state, really useful!
Great example. I've never really known how this was implemented so that's great to see
The same can be achieved with props. I think having multiple contexts for stubbing would be just as messy as prop drilling
Nice advice for if you're working with storybook too!
Love the way you explain! ♥
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.
Sounds nice for an api
Happy new year.
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
What is wrong with wrapping root element 20 times with providers?
@@N8X4TEIt gets hard to maintain real quick
Create a Providers component with all your providers and pass root elements as children, cleans up root file.
Good job love!
Great content!
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.
Very good. Thanks.
Great video
Interesting idea. I can’t tell if I like it yet but my intuition is telling me to avoid for some reason
I use this exacly but with react query
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😢
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
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)
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?
It’s basically a global store for dependencies that all your react components can load in when needed
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
@@hypeerjgreat explanation!
@@user-ri1vc4qv8j somehow I forgot about mocking functions ;b, so this is 3rd option
Really good content
Could you make a video react project structure like feature slice design
This is good💥
Yeah but if you do this, won't you have to wrap your app.js with a whole bunch of nested providers?
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.
@@yousefkhalil7540do you have a codebase that shows this?
What is wrong with the whole bunch of nested providers?
@@N8X4TE ugly looking code, sometimes you might have to rearrange your nesting a couple of times
@@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.
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.
vscode theme?
Cool video
Isn't It a kind of strategy pattern? Wyt?
Didn't understand much. I'll watch it again
I am not sure if making the layouts page a client component is a good practice
Is that what you got from this video?
@@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
@@therealsharat usually I make a separate file called providers and I use client at the top of that file.
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.
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
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!
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.
I don’t know. You really should not test the fetch. Test the function That mutates the response
I’m not testing the fetch
class lol
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.
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”
@@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.
second watch on this video. great content.
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
not a piano vid unsubbed
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
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