3 Ways to Avoid Prop Drilling in Vue/React

SdĂ­let
VloĆŸit
  • čas pƙidĂĄn 27. 07. 2024
  • 📗 Book (Updated Aug 2023): lachlanmiller.gumroad.com/l/v...
    🎉 Writing a book about tooling, testing and development philosophy: lachlan-miller.ck.page/92dfa0...
    🐩 Twitter: / lachlan19900
    Sick of passing props to deeply nested components? Here's a few alternatives I've used over the years, with my thoughts and recommendations.
  • Věda a technologie

Komentáƙe • 28

  • @AlexanderSadykov
    @AlexanderSadykov Pƙed 6 měsĂ­ci +3

    Thanks for the great video! I think you could have mention as well. They give us another way of passing props to children components. I agree that these children are not really children, since they imported and exist within the same parent component. But it can be a solution in some cases.

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      This is actually a good point and worth mentioning sometimes they said passing a property. You can just use slots more effectively.

  • @jackdrengr5069
    @jackdrengr5069 Pƙed 6 měsĂ­ci +3

    That's a great video. Thank you.
    I would also like to point out a couple more disadvantages of 1st and 2nd solutions. They won't work very nice if you need to have multiple instances of a deeply nested component that uses this data from the very top, but the data itself must be different. Let's imagine a situation where we have a list of usernames and a pretty complex components structure with an input to handle a username editing deep down there at the very bottom. Yes, we can update our store/composable to work with indices while updating the data, but that's not always possible and convenient.
    Also developers should keep in mind that such methods of storing data make it global. If you need the data to be unique or initially empty each time - this usually means that you should reset this data at some point. For example inside onBeforeDestroy hook in Vue.

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Good point. This is an interesting scenario. You could make a composable that defines the `ref` inside the `useXXX`. You could have a `watch` **outside** that notifies each instance when the parent changes something, and have each nested child react using its local data.
      Good point, thank you sharing this. I will try and talk about this use case in a future video!

  • @blessedonekobo
    @blessedonekobo Pƙed 6 měsĂ­ci +1

    Love the new video format

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Thank you!

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci +3

      I am experimenting with different things, hoping to grow a ton in 2024 :D

  • @lethanhphong7812
    @lethanhphong7812 Pƙed 6 měsĂ­ci +2

    Great video. I'm currently work on a micro FE project and for me I like to use Event Bus as a way to share data between micro apps. Or if less data I will use React Context instead to share data from the host-ui. Do you have any recommend for sharing data in micro FE project or make a video about micro FE using Vite. That gonna be great

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci +1

      I generally don't like event bus, but I think for micro frontend that's probably the only way to do it.
      I haven't done a micro frontend project before, I'd love to try. What are you building?

  • @AlexanderSadykov
    @AlexanderSadykov Pƙed 6 měsĂ­ci +1

    I'd love to hear how all these options play with tests. I mean how easy it is to test children component that uses Pinia vs the one that uses composable vs inject vs etc.

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Good point I should’ve talked a little bit more about this. In my experience provide inject and props work much better with test than piña when you need to introduce an additional dependency. I generally prefer not to mock like piña, so I create an entire store. It’s quite a lot of boilerplate. What do you generally do?

    • @AlexanderSadykov
      @AlexanderSadykov Pƙed 6 měsĂ­ci +1

      @@LachlanMiller I would agree. Props and inject are the easiest for me. And they are built-in, so no need to spend time to learn another API (e.g. on how to mock Pinia as you have said)

  • @igor-telmenko
    @igor-telmenko Pƙed 6 měsĂ­ci

    Thank you for analyzing this topic with consideration of earlier approaches.
    The applications that I currently support and develop started about 3 years ago (maybe earlier). That's why Vuex still works there. Some of them also have an Options API. What always surprised me about Vuex was its verbosity (not ergonomics, if you like). It was especially difficult during the tests. Therefore, from time to time I asked myself “am I solving the prop drilling problem correctly?”
    The Pinia and Composition API will probably be much more convenient. Including tests. Perhaps I should try Pinia. Most likely, projects will then have to be transferred to this tool.
    Yes, and for libraries, I agree with you that provide/inject would be more appropriate there.

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Yeah, Vuex is pretty verbose. What would you expect from something modelled on Redux, lol (apparently Redux is nicer now). Testing is still a bit of a pain, just need invest in test infrastructure and be disciplined. I tend to write more high level integration/e2e tests nowadays, what is your main testing methodology?

    • @igor-telmenko
      @igor-telmenko Pƙed 6 měsĂ­ci +1

      In our projects, most of the business logic is on the backend (php 8.2 with laravel). Therefore, most of the tests are there.
      On the frontend, I've only just come to the point of implementing tests everywhere. Before this I had only tried adding them in certain places.
      But regarding the types of tests. I often find it more convenient to test smaller parts of the system. Even individual services (classes). In this case, you need to create fewer mock objects. And the tests themselves look simpler. And if something breaks, it’s immediately clear where exactly.
      But in some cases I actually do a large integration test of some functionality. And as you noted in your book, this is more close to how the application actually works.

  • @robwatson826
    @robwatson826 Pƙed 6 měsĂ­ci +1

    Just stumbled on this video, really interesting! I had no idea Vue's state methods could be used outside of components.
    A bit of feedback on the format of this video: It's a bit tricky to follow then you have all your proposed solutions in the same files. It might be better to put all the functionality from specific solutions in a file, then have 1 file per "solution"?

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Hey, thanks for the comment & feedback!
      Re: reactivity -- Vue's reactivity system is **not** coupled to the runtime, you can use it not only outside of components but even outside of Vue (!!) You could just install `@vue/reactivity`, although you'd need to bring your own vdom and wire it up (fun experiment / future video idea, maybe!)
      Regarding the feedback, I will try to make separate files next time - I can see why this would be confusing.

    • @AlexanderSadykov
      @AlexanderSadykov Pƙed 6 měsĂ­ci

      @@LachlanMiller you can also use //#region in VS Code to keep everything in the same file and collapse/expand parts of it when needed :)

  • @jessicaryan9820
    @jessicaryan9820 Pƙed 6 měsĂ­ci +4

    This is why we have Pinea in Vue

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      Yep, Pinia is what I normally default to. Weird name but it sure works great.

    • @JeffPohlmeyer
      @JeffPohlmeyer Pƙed 6 měsĂ­ci +1

      If content needs to only be shared from parent to children then Pinia is likely overkill when you can just use provide/inject

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci

      @@JeffPohlmeyer Interesting idea, I haven't used provide/inject much. Do you use this a lot? When do you decide to reach for that vs Pinia?

    • @JeffPohlmeyer
      @JeffPohlmeyer Pƙed 6 měsĂ­ci +2

      @@LachlanMiller if many components not in a direct descendancy need some shared state I go with Pinia. If the shared state is only needed by components who have a linear relationship then it's much less boilerplate to use provide/inject

    • @LachlanMiller
      @LachlanMiller  Pƙed 6 měsĂ­ci +1

      @@JeffPohlmeyer provide/inject is definitely more concise - I think it can be used effectively, for sure, might need to giv it another chance in my next app...