I am working on a React project which is divided into several modules and each module contains several components. There is also a commons module which contains components which are common to two or more separate modules. I am using context API for managing all the state. Below is the structure of the parent component(App.js). Module1Container, Module2Container... contains components of respective modules.
return(
<CommonsContextProvider>
<Module1ContextProvider>
<Module1Container />
</Module1ContextProvider>
<Module2ContextProvider>
<Module2Container />
</Module2ContextProvider>
<Module3ContextProvider>
<Module3Container />
</Module3ContextProvider>
</CommonsContextProvider>
)
I mainly want the states to be seperate as a single context for every module will make it too much cluttered. Is it a good idea to have a separate context for each module and a common context for commonly used state across modules? Don't this structure voids the single source of truth rule? Better suggestion is most welcome.
This method currently have no problem, but on the long run, if you need to maintain the project single source of truth is still better,
For single source of truth use redux (redux-hooks) and
incase you need to have modular kinda of view of states use different reducers for different component and common reducer for global state,then combine them using combineReducer of redux
Related
I'm really new to React and need to ask.
Can I have a ReactJs Redux store in a library and then use that library in an App that also has a Redux store?
Both of them do this:
<Provider store={store}>
..App
</Provider>
I learn ReactJs and am not sure I understand how this is built up how Webpack is loading the code here.
Will these two React Stores collide?
Can they exist independently?
Can they share Reducers? (let's say the App want to use the library Redux store and send a dispatch to it )
I have tested doing some of this but can't make it work. It's like Redux after first loading the library Redux store then it can't load the App store but I'm a novice so must ask
Will these two React Stores collide? / Can they exist independently?
Two different stores created with createStore will not collide, and can exist independently.
behind the scenes, each store instance has a subscribe method, and its own subscribers array.
When using the react-redux Provider component, you are sending an instance of the store down the component tree with React's context API. The instance will be available to all children and decedents of the component which rendered the Provider. If there is another Provider in the way, that Provider's value will override the higher up Provider.
Thus, if you use another Provider with another instance of a store in your library, it will take effect only for the component tree starting from your library component. With the correct composition, there will be no collision.
Can they share Reducers?
Reducers are nothing but pure functions, meaning they shouldn't have any side effects. So you could export and reuse the same reducer logic if you want, you'll just need to register them with every store instance.
Lastly, I disagree with other answers here which claim you shouldn't use multiple stores. You have the exact use case where a separate store would be justified, where you have your main application using one store, and you have a standalone library that uses another unrelated global state.
In my opinion, everything is possible in the programming world, definitely, having a multi-store is possible too.
You asked several questions, first of all, I answer them and then explain a little bit more.
Can I have a Reactjs Redux store in a library and then use that library in an App that also has a Redux store?
Yeah, it's possible, the famous library that makes Redux easy to use is Redux Toolkit, which has a very easy flow to use and implement in your application, even it has a CRA template that you can create your application (zero-config) based on redux npx create-react-app [my-app-name] --template redux or redux-typescript npx create-react-app my-app --template redux-typescript. it works properly.
Will these two React Stores collide?
Can they exist independently?
No, they won't collide because each store (never mind it is redux, mobx, or whatever) has a Provider and you should wrap part of your application or entire of it by using that <Provider store={store}>, so if you wanna have two stores, you can add two Providers and they won't collide. but, in connecting, and getting some data from stores, you should pay attention that which Provider you are going to call from. so they will be able to exist independently.
<ReduxOneProvider store={storeOne}>
<ReduxTwoProvider store={storeTwo}>
<MobxProvider store={mobXStore}>
<App>
</MobxProvider>
</ReduxTWoProvider>
</ReduxOneProvider>
But, totally, I'm not a fan of having multi-store, for more info read here
Can they share Reducers? (let's say the App want to use the library Redux store and send a dispatch to it )
Yes, you know, reducer functions are separate pure functions, located in a folder, when you wanna build your stores, you should gather these functions and combine them, so, the answer is yes, but please consider, the connect function which comes from react-redux want two functions, mapStateToProps and mapDispatchToProps, inside the second you can call a reducer by using dispatch function. so you will have re-render in all stores.
my opinion:
Please avoid having a multi-store, even having one and dealing with it, makes the project a little bit hard to maintain. how you wanna deal with multi. it makes complicated issues.
Yes it is possible.
To keep it simple, library is completely independent package where you can use the redux in normal way. And as you export the library's components to outer world, in same way export the store or dispatch which you would like to use in your application which is consuming the library.
I have a little question about Angular Components.
I often read that you should use components only to display data and interact with the user, and for your "business logic" you should prefer services.
So my question is the following (just an example):
Let's say I have made a component to upload files via drag and drop. I have the logic to get the data from the drag and drop and store it in an array (and maybe much more other functions) inside that components typescript file.
Now when I am including this component twice inside one parent component (because I need two upload fields for example), are both referencing to the same or is also the program logic inside that component created twice for each instance?
If so, then I should try to keep as much shared program logic as possible in singleton services so they are only created once at runtime and not wasting memory etc., shouldn't I?
Hope somebody understands what I am meaning :).
thanks in advance!
If you add the component twice into your parent, then two different instances will be created (each owning unique scope).
You should however abstract upload/handling logic into a service. Provide that service in module to make it a singleton. If you want instance per component, then provide it inside component.
If you create two components in your template which are similar for example:
<app cumstom></app custom>
<app cumstom></app custom>
This will result in two objects being created who both have their own model (data) and view. They don't know anything of each other.
If you want them to communicate it is often smart to use a service which you can inject into both components so they can share the same data. If a service is provided in your ngmodule is will only be created once (so it is a singleton).
Well I think what you need is a smart component, where you can put your boths uploads-component and inject your service logic in this smart component. The smart component will be responsible to provide the bridge of the common logic between the two components.
I'm somewhat new to React, and I'm trying to figure out where the best place is to put various functions that need to be used across my app.
For example, I have a function some code that returns a document_type key based on the document extension that is passed to it.
I also have a romanize function that takes a number and turns it into a roman numeral.
I also have a set of functions that are grouped around making API calls and parsing the response.
All of these need to be accessed in various places across the app. It's my understanding that the "React Way" is composability through component creation, but it's hard for me to see how these would make sense as components since components have to return JSX I believe.
You could create e.g. a utils file, export your helpers from there, and import them when needed:
// utils.js
export function romanize(str) {
// ...
}
export function getDocumentType(doc) {
// ...
}
// App.js
import { romanize } from './utils';
There are some situations where you will need a helper functions like these and setting those up in a util or helpers folder is a great way to handle that.
However, to take full advantage of React, I'd suggest thinking about if there is a way you could make a shared component instead. For functions such as your romanize function, you can make a React component that formats the number you pass it and displays it in a span. This is the same approach react libraries use, for example the react-intl library recommends using their <FormattedMessage /> component instead of their formatMessage helper function.
For example,
const RomanNumeral = ({ number }) => {
// romanize logic here
return <span>{result}</span>
}
Then you can use it like so:
<RomanNumeral number={5} />
The "react way" is to structure these files in the way that makes most sense for your application. Let me give you some examples of what react applications tend to look like to help you out.
React has a declarative tree structure for the view, and other related concepts have a tendency to fall into this declarative tree structure form as-well.
Let's look at two examples, one where the paradigm relates to the view hierarchy and one where it does not.
For one where it does not, we can think about your domain model. You may need to structure local state in stores that resemble your business model. You business model will usually look different from your view hierarchy, so we would have a separate hierarchy for this.
But what about the places where the business model needs to connect to the view layer. Since we are specifying data on a per component bases. Even though it isn't the view or styles or how the component behaves, this is still colocated in the same folder hierarchy as the react component because it fits into the same conceptual structure.
Now, there is your question of utilities. There are many approaches to this.
If they are all small and specific to your application but not any part, you can put them in the root under utils.
If there are a lot of utils and they fit into a structure separate from any of your existing hierarchies, make a new hierarchy.
If they are independent from your application, either of the above approaches could become an npm package.
If they relate to certain parts of your app, you can put them at the highest point in the hierarchy such that everything that uses the utility is beneath the directory where the utility lives.
Shared Conmponents is definetly the react way but having reusable functions in the utility/helper folder is always handy.
Here is how I would do it.
You could create a utility folder inside src folder where you could export all the reusable functions
--| src
----| utility
-------| formatDate.js
-------| formatCurrency.js
-------| romanize.js
----| components
----| hooks
----| api
Then you could import the functions inside your components
In front-end apps there is often data which needs to be accessed by many components. Routing is one example, another is configuration data, e.g. feature switches, default language, etc.
In an app that isn't using any particular framework, I might share this configuration data across modules using
export class Configuration {
static getConfig () {
// get the config from the server
return axios.get('/config').then(function (response) {
return response;
})
}
}
Then import this class into any module that needs to access configuration data. With some front-end framework, it's obvious how to share such "global" data, e.g.
AngularJS - Configuration should be defined as a service that's dependency-injected into any controllers/directives/services that need to access config. data
Vue.js - use a mixin
However, when using ReactJS it's not obvious which approach should be used. Possible options are:
A plain-old JavaScript module. Encapsulate the data to be shared as a function/method, and import it into any React components that need to access it. The seems like the simplest approach, but I have the feeling that when writing a ReactJS app everything should be defined as a component, rather than JavaScript classes/functions.
Redux seems to be recommended approach for sharing-state within large apps, but this feels like overkill for smaller projects
Something else?
but I have the feeling that when writing a ReactJS app everything
should be defined as a component, rather than JavaScript
classes/functions.
I really don't see a reason why everything should be a component in React. If it is just data, you can create a single instance of that JS object say and import that anywhere you need it.
I have used similar thing in my app, where I had a "global" kind of object which was saving different configs etc, and then I was using that in the components which needed that data.
Here is also some more info about component communication in React.
A plain-old JavaScript module. Encapsulate the data to be shared as a function/method, and import it into any React components that need
to access it. The seems like the simplest approach, but I have the
feeling that when writing a ReactJS app everything should be defined
as a component, rather than JavaScript classes/functions.
I disagree, React is a library that helps to create user interfaces through components but it doesn't mean that (services, translations, configuration data) have to be built into components, on the other hand, it's actually discouraged you shouldn't couple your services/configuration to a library
you should limit the scope of React to what it is used for. So using plain-old JavaScript modules feels the right way to implement a simple react app.
Redux seems to be recommended approach for sharing-state within large
apps, but this feels like overkill for smaller projects
I think it depends on the complexity of the app rather the size, here is where you should think on, how does your app will evolve or if redux isn't what you really need to remove all this data-sharing dependency within React.
Something else?
The react context (discourage)
The observable pattern
https://www.npmjs.com/package/react-observable-subscribe
I think you should go for the redux solution. It sounds like an over kill but it has an added advantage of having a global state object, therefore you can easily choose when to re-render your app when data is shared across compoents.
you can use context in react :
https://reactjs.org/docs/context.html
or you can create a global variable in window object too
the other way is to use observer design pattern plagin and use it.
mobX or other stateManagement component is good too beside redux
I've noticed that react projects tend to be organized like this,
/src
/actions
userActions.js
settingsActions.js
/components
userComponent.js
settingsComponent.js
/containers
userContainer.js
settingsContainer.js
/reducers
userReducers.js
settingsReducers.js
coupled on type rather than functionality like,
/src
/user
userActions.js
userComponent.js
userContainer.js
userReducers.js
/settings
settingsActions.js
settingsComponent.js
settingsContainer.js
settingsReducers.js
Why is that? To my understanding React is good in part because it couples css, html and js together instead of having them separate. Why not do it with the file structure as well?
There is no one true way to organize your files and directories, it varies with the opinions. But people still wonder what the best method for organising the code is.
I usually prefer the structure where containers, components, actionCreators, services and reducers are segregated. Whichever pattern you are following, you can make it more and more granular once your codebase scale up. I hope you are familiar with the idea of Presentational vs. Container components.
In the first pattern, components/ just hold the dumb stateless components that just takes props. This pattern very well support the concept of reusability. When you develop a large application, it happens quite often that you need to create a component that you definitively know you won’t reuse anywhere else, but you need it.
The containers/ have the stateful components which make API calls. Same way, if you are using redux in your application, many people tries to follow the ducks pattern where you define all the reducers in a single directory along with your root reducer, just to make things more granular and easy to access, and you don't have to jump between files to create an action.
This is just my perspective, but as I mentioned earlier, it totally depends on the use case of an application and also the opinion of the one who develops it. An alternative is to organize files by functional area as you mentioned in your second directory structure, with folders like users and settings kind of functionalities. This organization style starts off deceptively simple. But inevitably you end up with a folder common where you store very basic and common components like button, which are used all over your app, eventually you will end up with common/components and common/containers, but at one level deeper.
In short, start simple with whichever structure you want, you will eventually make it finer and finer with your use case and scale.