I just started learning Vue and Vuex. I saw that I have the same code in different components. I started using Vuex and i store my data inside index.js and it's really helpful.
My questions is, how can I store click functions with vuex. In the code below is simple example
<button #click="clickMe">Click Me</button>
methods: {
clickMe() {
console.log('Hellouu')
},
}
Keeping the logic of a component in itself is what component-based approach is about. A click listener on a component or its sub-element is very personal and private to a component.
Mixins
But.. let's say you have a situation where you have the same exact logic that needs to be executed on-click on multiple components, the answer will be to use mixins. Store is not the place to do it. This holds and is true for any case where you need to 'share reusable functionalities'.
Apart from providing flexibility, mixins have a number of benefits, for instance, you can take advantage of the option merging rules within mixins to override the onClick() method described in a mixin to cater for a special case within one of the components, but continue to use the rest of the common logic the mixin contains.
Note: Be careful though, Hook functions with the same name are instead merged into an array so that all of them will be called. Mixin hooks will be called before the component’s own hooks.
Read more (optional)
As a great real world example check out this repository: https://github.com/buefy/buefy. Its a UI components library that is built with Vuejs. You can find many more examples and best practices in such open source repositories and these are always a great reference point for writing better code.
Related
I'm coding a small library with a simple structure: one parent component can contain multiple components of the same type as direct children. Here is a sample schematic diagram for the app:
By current design, a ChildComponent must address a variety of properties of their parent MainComponent, and I am looking for a good practice that can help achieve that or an alternative of an app structure that will lead to a good practice.
My considerations:
Using Context API. This won't go well with the goal in mind because of the nature of contexts. As per linked documentation:
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
Passing all required props from MainComponent to ChildComponent. Despite I meet this approach quite often, I don't think it is good because it leads to duplicate code.
The simplest way is with Props, as you already mentioned. If you are passing only one level down it is probably the best option:
https://reactjs.org/docs/components-and-props.html
If you need to pass code to several children and grandchildren, using props will get annoying, that is called "propdrilling". You can avoid it using a Context that will provide to all the components that want to consume it:
https://reactjs.org/docs/context.html
Another alternative for larger applications is Redux. Is has a store and enables your components to interact with the Redux store. The downside is that it requires a lot of boilerplate.
https://react-redux.js.org/
Introduction
React is really flexible, it seems that we are not forced to follow a specific architecture when programming interfaces, unlike with other libraries, it is something like coding a plain view. With small web apps, this is cool, but... as soon as your app starts to grow, the speed with which you code will decrease progressively, contrary to if you had defined your architecture from the beginning of the principles.
My Architecture
In my case, I am not using Redux for state management... instead, I am using React Context + React Hooks.
This is my current project structure (serverless app built using firebase):
/app
/components
/Activity
/Authentication
/Profile
/Buttons
/Text
/Inputs
/Giphy
/Messaging
/HOCs
...
/screens
/Activity
/Authentication
/Profile
/Messaging
...
/contexts
/Users
/Content
/Auth
...
/hooks
/auth
/profile
/users
/content
/badges
/i18n
...
/navigation
/Stacks
/Tabs
...
/services
/third-party
/firebase
/api
...
/lib
/theme
/styles
/utils
/functions (backend)
As you can notice, I am using some kind of domain-driven design to structure my project files.
Also, I am separating concerns from screens and components using hooks, and managing complex state (or which need to be synchronized between routes) inside contexts that contains the respective reducers.
This seems to me like some kind of MVC. Where the View is composed by all my React Functional Components, the controller is composed by all my Business and UI hooks, and the data of my Model is contained inside Contexts (or, at least the dynamic data, because of efficient reasons).
As you can see, I have a folder "services" which is just the interface that my business hooks use in order to connect to my server (cloud functions).
Questions
Does this architecture have a name (flux/redux??)? I mean, with the passage of time as a React programmer, mistake after mistake, I have ended up organizing my projects like this, in a "natural" way.
Is it an anti-pattern to split all my components logic with hooks? I mean, all the functional components of my project just contain the event handlers or the JSX to render the UI. I have moved every single block of code to hooks, some of them contain the logic of my business, others simply complex logic related to the graphical interface (animations, ...)
Which advices do you give to me in order to refine my current architecture?
useSelector with React Context? I have implemented some custom hooks that just read and compute derived data from contexts... as I can't use "useSelector", I don't know if this is something typical, because they just consume the necessary contexts (useContext) and then execute some calculations.
Is it Redux really necessary? For a medium-large project, I have handled it well using React Context and with the help of the hooks my code has been quite clean. Do you think that over time, as the project continues to grow, it will be necessary to move to Redux?
Are react hooks the controllers of an application?
Well, not completely sure that this is the right place to put questions like this, but let try to answer, from my point of view, to these points.
Answers
I don't think this specific architecture has a name (like, for example, this one, that has a name https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/). In any case the name would not be "Flux" or "Redux" since these names are more related to how data is treated instead of how folders are structured in the project. I don't think there is some strict rule about folder hierarchy to follow to be fully compliant with Flux or Redux patterns. For sure there are best practices and conventions, but they are not mandatory.
To answer this point, let me share this link https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 about an article posted by Dan Abramov. I am sharing this article because of the last update made (the article is dated 2015, but there is an important update made in 2019). As you can see seems that you are doing it good since you are putting the core logic in hooks. Just a note about this point: you said "functional components" but I think you were referring to "presentation components", this is an important distinction because "functional component" means that your component is based on a function (instead of a class), "presentation component" instead means that the component does not contain business logic. A "presentation component" can be both class-based or functional and a functional component can contain business logic (class-based component are being replaced by functional ones, but this is another story).
Some advice: be coherent with capitalization and casing (you are mixing uppercase and lowercase, dash-case and camelCase, usually I like to name every file or folder in dash-case, but it depends on you); nut sure if HOCs folder should be here; maybe you can put all the utils (lib, theme, styles and utils itself) in a directory called utils where each util is named property;
About context, and this is a controversial topic, just want to share some considerations taken from docs https://reactjs.org/docs/context.html#before-you-use-context and share my opinion on that. The idea behind context is "Context provides a way to pass data through the component tree without having to pass props down manually at every level", as per documentation subtitle. So, basically, it si something created to avoid "property drilling", as exposed here https://medium.com/swlh/avoid-prop-drilling-with-react-context-a00392ee3d8 for example. This is just a personal point of view but, maybe, is better to introduce Redux for global state management instead of using Context API.
Don't be scared to use Redux. Be scared if, while using Redux, you have tons of duplicated lines of code. In this case you should think about how to abstract your actions and reducers (for example with action creators). If you will be able to generalize stuff like "getting a list of items from your backend", you will realize that your code will not just have less lines of code than a repetitive one, but it is even more readable and coherent. For lists, for example, you may have an action like const getListOfNews = list("NEWS_LIST", "/api/news/"); where list is an action creator like const list = (resource, url) => (params = {}) => dispatch => { // your implementation... };, something similar with reducers.
No, they just "let you use state and other React features without writing a class" as said here https://reactjs.org/docs/hooks-intro.html from docs. It is important to avoid trying to adapt a pattern like MVC to something that was created with different ideas, and this is a general advice. Is like if you are coming from Angular and you try to work in the same way in React. Basically you should work with React, or other libraries/frameworks, without trying to transform them from what they are to what you already know.
With the introduction of hooks in React, the main confusion now is when to use function components with hooks and class components because with the help of hooks one can get state and partial lifecycle hooks even in function components. So, I have the following questions
What is the real advantages of hooks?
When to use function components with hooks vs Class components?
For example, function components with hooks can't help in perf as class components does. They can't skip re-renders as they don't have shouldComponentUpdate implemented. Is there anymore reasons?
The idea behind introducing Hooks and other features like React.memo and React.lazy is to help reduce the code that one has to write and also aggregate similar actions together.
The docs mention few really good reason to make use of Hooks instead of classes
It’s hard to reuse stateful logic between components Generally when you use HOC or renderProps you have to restructure your App with multiple hierarchies when you try to see it in DevTools, Hooks avoid such scenarios and help in clearer code
Complex components become hard to understand Often with classes Mutually unrelated code often ends up together or related code tends to be split apart, it becomes more and more difficult to maintain. An example of such a case is event listeners, where you add listeners in componentDidMount and remove them in componentWillUnmount . Hooks let you combine these two
Classes confuse both people and machines With classes you need to understand binding and the context in which functions are called, which often becomes confusion.
function components with hooks can't help in perf as class
components does. They can't skip re-renders as they don't have
shouldComponentUpdate implemented.
Function component can be memoized in a similar way as React.PureComponent with Classes by making use of React.memo and you can pass in a comparator function as the second argument to React.memo that lets you implement a custom comparator
The idea is to be able write the code that you can write using React class component using function component with the help of Hooks and other utilities. Hooks can cover all use cases for classes while providing more flexibility in extracting, testing, and reusing code.
Since hooks is not yet fully shipped, its advised to not use hooks for critical components and start with relatively small component, and yes you can completely replace classes with function components
However one reason that you should still go for Class components over the function components with hooks until Suspense is out for data fetching. Data fetching with useEffect hooks isn't as intuitive as it is with lifecycle methods.
Also #DanAbramov in one of his tweets mentioned that hooks are designed to work with Suspense and until suspense is out it's better to use Class
Hooks greatly reduce the amount of code you need to write and increase its readability.
It is worth noting though that there are hidden processes going on behind (Just like component did mount etc.) that mean if you don't understand what is going on it can be difficult to troubleshoot. It is best to experiment with them and read through the docs fully before implementing on a live project.
Also there is still limited support/documentation for testing hooks compared to classes.
https://dev.to/theactualgivens/testing-react-hook-state-changes-2oga
Update 28/08/2020
Use the react hooks testing library with custom hooks for testing
https://github.com/testing-library/react-hooks-testing-library
Officially it sounds like hooks will completely replace classes?? maybe one day, but think about it; hooks have been around for 3 years (as of Mar 2021), and there are pros and cons in adopting them (More pros than cons... don't get me wrong)
I have plenty more experience myself with state management/classes and after doing a lot of research and testing, I found out that we need to know both classes and hooks very well. Hooks require a fraction of the code for simple components and seem excellent for optimizing HOCs. Meanwhile classes seem better with routing, container components and asynchronous programming for example.
I'm sure there are plenty more cases where each technology is better, but my point is that programmers need know both hooks and classes very well specially when working on projects with 100,000+ lines of code and millions of users. Read more here: https://stackoverflow.com/a/60134353/11239755
With the introduction of hooks in React, the main confusion now is when to use function components with hooks and class components because with the help of hooks one can get state and partial lifecycle hooks even in function components. So, I have the following questions
What is the real advantages of hooks?
When to use function components with hooks vs Class components?
For example, function components with hooks can't help in perf as class components does. They can't skip re-renders as they don't have shouldComponentUpdate implemented. Is there anymore reasons?
The idea behind introducing Hooks and other features like React.memo and React.lazy is to help reduce the code that one has to write and also aggregate similar actions together.
The docs mention few really good reason to make use of Hooks instead of classes
It’s hard to reuse stateful logic between components Generally when you use HOC or renderProps you have to restructure your App with multiple hierarchies when you try to see it in DevTools, Hooks avoid such scenarios and help in clearer code
Complex components become hard to understand Often with classes Mutually unrelated code often ends up together or related code tends to be split apart, it becomes more and more difficult to maintain. An example of such a case is event listeners, where you add listeners in componentDidMount and remove them in componentWillUnmount . Hooks let you combine these two
Classes confuse both people and machines With classes you need to understand binding and the context in which functions are called, which often becomes confusion.
function components with hooks can't help in perf as class
components does. They can't skip re-renders as they don't have
shouldComponentUpdate implemented.
Function component can be memoized in a similar way as React.PureComponent with Classes by making use of React.memo and you can pass in a comparator function as the second argument to React.memo that lets you implement a custom comparator
The idea is to be able write the code that you can write using React class component using function component with the help of Hooks and other utilities. Hooks can cover all use cases for classes while providing more flexibility in extracting, testing, and reusing code.
Since hooks is not yet fully shipped, its advised to not use hooks for critical components and start with relatively small component, and yes you can completely replace classes with function components
However one reason that you should still go for Class components over the function components with hooks until Suspense is out for data fetching. Data fetching with useEffect hooks isn't as intuitive as it is with lifecycle methods.
Also #DanAbramov in one of his tweets mentioned that hooks are designed to work with Suspense and until suspense is out it's better to use Class
Hooks greatly reduce the amount of code you need to write and increase its readability.
It is worth noting though that there are hidden processes going on behind (Just like component did mount etc.) that mean if you don't understand what is going on it can be difficult to troubleshoot. It is best to experiment with them and read through the docs fully before implementing on a live project.
Also there is still limited support/documentation for testing hooks compared to classes.
https://dev.to/theactualgivens/testing-react-hook-state-changes-2oga
Update 28/08/2020
Use the react hooks testing library with custom hooks for testing
https://github.com/testing-library/react-hooks-testing-library
Officially it sounds like hooks will completely replace classes?? maybe one day, but think about it; hooks have been around for 3 years (as of Mar 2021), and there are pros and cons in adopting them (More pros than cons... don't get me wrong)
I have plenty more experience myself with state management/classes and after doing a lot of research and testing, I found out that we need to know both classes and hooks very well. Hooks require a fraction of the code for simple components and seem excellent for optimizing HOCs. Meanwhile classes seem better with routing, container components and asynchronous programming for example.
I'm sure there are plenty more cases where each technology is better, but my point is that programmers need know both hooks and classes very well specially when working on projects with 100,000+ lines of code and millions of users. Read more here: https://stackoverflow.com/a/60134353/11239755
The following is from an issue I posted on EmberJS GitHub, but Stack Overflow is better suited for a discussion than GitHub.
I am building a few complex components at the moment including composite components and I hit a roadblock with the extreme isolation components live in.
There are several cases where I don't need the components to trigger an action on a controller, but where a controller needs to trigger a behaviour change on the component.
Problems is that the components don't know about the controller and the controller is not creating the components either: they are defined in a template.
I kind of solved the problem by subclassing the Ember.Component class to offer a way for messages to get through components.
The new component subclass breaks the on purpose isolation of components that shouldn't know about the outer controller.
The 2 less invasive options I found to make component methods calls from outside are:
Cache component / name of instance pairs in a global array like
App.components, then call a component method with
App.components['name'].method()
Trigger events from outside, register and handle them in the
components. However in that case I am passing an eventSource object
to the component, often a controller like so: {{my-component
eventSource=controller}}
My question is about how could we solve this problem in the most elegant and less invasive way possible for components ?
For achieving composite components, using the components like lego pieces, it seems impossible to me at the moment to see how we can achieve that goal without breaking the components isolation.
Any input, ideas, solutions, discussion is very welcome.
Note: By the way, the first method that breaks the component isolation is inspired by the work done on the ember-bootstrap components: https://github.com/ember-addons/bootstrap-for-ember
The author had to solve the same problem of being capable of triggering methods inside the components from outside.
Another note: Just for the record, another way to access a component is to use Ember.View.views['name'] where name is a view name you gave to your component. However I feel dirty to make such calls, even more from a controller.
In general, I would try to solve this by binding properties to your component, which could then change according to computed properties or observers based on those properties.
For instance, instead of trying to call a method like deactivate on a component, bind a property such as active to a property in the template:
{{my-component active=formEnabled}}
I'm hesitant to recommend passing an eventSource to components as a general solution (like your {{my-component eventSource=controller}} example). I imagine this could work with a class or mixin that just emits specific events and is tightly coupled with your component, but I'm struggling to come up with a use case that justifies this approach.