How better organize React-components interactions? - reactjs

I am building SPA with React and have the following structure of UI-components:
App (base layout with navbars and footers)
EventsIndex (Load Events data from API)
FilterBar (common components where current filter settings is shown)
EventsTable (show Events data for desktop)
EventsAccordion (show Events data for mobiles)
SomeOtherIndex...
EventsTable and EventsAccordion have a lot of common logic such as pagination, filter's and sorting's handlers.
I have to lift up handlers from child components(EventsTable and EventsAccordion) to parent EventsIndex. But for me it seems not the best way.
Am i wrong?
What the best practice in such cases?
Should i use Redux? If no, when it better to use it?

React is all about Components, I would say the most important part when starting to design a React App is structuring your Components well.
There are different ways to structure your components well, below are some:
Container Components: When designing your app identify the container components, these are the components which are going to hold state and also manipulate them based on events.
Coming to your question: I have to lift up handlers from child components(EventsTable and EventsAccordion) to parent EventsIndex. But for me, it seems not the best way. Should I use Redux?
Answer: When using container components only a few components are going to deal with the state and any child hierarchy ( Child Components ) are going to be stateless components / ( Functional Components ), so in order to update the state they will have to have handlers passed down by their Container Components, using which these components are going to update state. ( This is absolutely fine, that's the way it should be )
Coming to REDUX, using REDUX in such small scenario is not recommended, I would not recommend it, because it would be an overkill, REDUX is apt in a much complex scenario when you would like to share some state between two component trees, but still you could use REDUX but its just that, its not recommended.
HOC ( Higher Order Components ): Whenever you have some functionality which is reusable, consider creating a HOC
Please check : HOC
Break Components to Smaller Re-useable pieces: This is often very important whenever you see that a component contains code which is used elsewhere, go ahead and make it a Separate Component, thus making it Reusable.
Please check this, this has a bunch of best practices
https://www.toptal.com/react/tips-and-practices
When to use REDUX ?
Basically, you need to be using REDUX, when keeping the state in a top-level root component is no longer sufficient, like for example : ( you have two branches out from root component, one of the child component in branch A wants to access some state in branch B's child, then you need to move it to the root component and again pass it down, such cases are apt for REDUX ).
Please check this source: https://redux.js.org/faq/general#when-should-i-use-redux

You can follow a container type implementation - which means that if there is some common logic between components, they can be encapsulated within a component that acts as a container for these two components and provides the necessary common logic / data.
So, for example in your case it'll be something on the lines of
- EventsIndex (Load Events data from API)
- FilterBar (common components where current filter settings is shown)
- EventContainer (where common logic resides for both your components)
- EventsTable (show Events data for desktop)
- EventsAccordion (show Events data for mobiles)
where EventContainer provides the common props such as pagination, filter's and sorting's handlers.
Hope this helps :)

The best approach that we follow in a team setting (and is opinionated; and probably won't fit in everyone's scenario) is to break the app into logical structures.
- src
- Utils (reusable methods such as sorting, pagination, etc)
- UI (Reusable UI components such as buttons, modals, etc)
- Services (API Calls to the database, further divided by entities /users /posts etc)
- Components (Hierarchy of components)
- EventsIndex (uses the service directory to make API calls)
- EventsIndexContainer (if following container encapsulation pattern)
- EventsTable
- EventsAccordion
If the handler isn't component specific, I'd suggest move it to the utils folder (so that you have a single responsibility pattern as well as a single place to modify your logic rather than in two places) and pass down the handler to the table and accordion from the EventsIndex component or a EventsIndexContainer component that further encapsulates your logical components (the later one is preferred my many who I've worked with).

Related

What is proper or effective way for Composition of React Component?

I have multiple view in my application, I need helpl in how to use reusable component effectively ? Is it ohk if I create viewspecific component from reusable component ? - Generic Tree View . For users View which will render with user specific data and actions .
I have written re useable component in my react app.Which I have to use it with different data and action is it ohk to creat new component which use resuable component and provide data related to that ?
i.e
Component - DepartmentTree which renders and some functions related to Department. So finaly I will render
Component - usersTree same way here it calls and methods related to users . In the users view I will render
It's definitely OK to create a view-specific component that renders a reusable component. You could let this depend on how big your page is. If it includes a lot of components, then do split them up in view specific components.
About the data, you have a few options... First of all you could map the data response to a general structure that your TreeView component can read, so you only need to pass some props to the TreeView component. You could do this in the redux reducer.
If you require specific data different behaviour, but you still want to use the reusable TreeView component, you could think about creating a Higher Order Component. This component will wrap your reusable component and add some specific logic to it. You can read about it and see some good examples here: https://reactjs.org/docs/higher-order-components.html
The most important thing I always keep in mind: It's not always about how you finally do it, it's about keeping it simple, understandable and consistent.

React state vs. Redux state (real usecase)

I have read multiple tutorials how to make CRUD in React with Redux bot none of the authors explained why they are using Redux. (Like they are only using it for fancyness or because all other are using it.)
Citate from here:
People often choose Redux before they need it.
Through further researching i learned that Redux is good for:
Share state between components
Let some data be accessable in the entire application
It does not exist a wrong or right. But only the do what makes sense.
My usecase
I have a component that uses a shared component:
¦-- domains/FooManagement/Components/Editor.jsx <-- Most-parent of the editor
¦-- domains/FooManagement/Components/..the children of Editor.jsx
¦-- shared/Components/Tabs/Tabs.jsx <-- Most-parent of the tabs
¦-- shared/Components/Tabs/..the children of Tabs.jsx
Tabs.jsx is used in Editor.jsx.
Which is the right approach?
Approach 1: React state (I think its the right one)
Every dynamic rendering that can happen is stored in the state of Editor.jsx.
onClick on a tab (nested shared component) calls a callback written in Editor.jsx that updates the state in Editor.jsx. This state change then rerenders the new active tab
That means that on every other component like Editor.jsx that uses the same nested Tabs.jsx, the changes for the tabs must be handled in the editor.
Code example:
/**
* domains/FooManagement/Components/Editor.jsx
* or
* domains/BarManagement/Components/Editor.jsx
*/
onTabChange(activeTab) {
this.state.activeTab = activeTab;
this.setState(this.state);
}
I think this is the right approach because:
I dont need the state of the editor or the tabs component in the entire application. But only on this view one time. Like the short term duration definition.
Approach 2: Redux state
Editor.jsx has its own state
Tabs.jsx has its own state
States are stored in Redux
Editor.jsx dont passes data down to Tabs.jsx because Tabs.jsx takes the data from the Redux store
Benefit:
The code example above must not be in Editor.jsx because its not the editor's interests how the tabs component behaves. (Or should the editor interests?)
I think this is bad because
Its too much magic in here. Immagine there comes more components in the editor like sortables, tables, etc. In the Editor.jsx you will not see what can render your view. It is hidden in the other components.
But if its all handled in Editor.jsx, you have the overview and the control of all what must be rendered on any change.
What is the right approach for you?
speaking of real usecases, I'm working on an everyday growing project, at first, pure React state management seemed like a very convenient way to develop, and it was working just fine when the components structures were still somehow flattened, but as we go along it, the project gets more complicated and by complicated I mean, more component become nested, and one parent has a serie of nested children, so we have to pass props all the way from the parent to the most furthest child, and whenever we need to rerender the parent, all the children have to go through this cycle also, as for your case, if you know that your project won't get way more complicated, and Tabs.jsx won't have maybe something like form that contains further nested subForm that contains a Grid maybe, you surely don't need to complicate your life with Redux, but as I stated earlier, for us we started to notice that at this stage, integrating Redux would be considerable

Where to write logic related to component that doesn't affect the UI directly

I have a component which contains a textarea. Whenever I enter text I run a set of validations against the text and depending upon results I update the UI. You can assume the code to be like this:
onTextChange(e) {
const results = this.runValidations(e.target.value)
}
Now, the problem is this.runValidations is like 100 lines of code sitting right there in the component but doesn't affect the UI directly and is specific only to the component and its child components. But, it makes my component file bloated.
So, is there any convention that other people follow in their React-Redux apps to handle such logical code that is specific to the component but is not part of the UI logic? Where do they place such code?
At the end of the day, most business logic doesn't have a lot to do with React/Redux - so they can usually be shovelled out into their own utility functions or classes. Which is great for a few reasons
a) easier to test because it hasn't zero linkage to React/Redux and
b) keeps your actions light, and
c) more encapsulated - having minimal knowledge of react/redux is not a bad thing.
It's all just Javascript - there is nothing wrong with importing custom business classes or utility functions.
Edit
My folder structure will typically look like:
my-component
child-components
Child1.js
_Child1.scss
Child2.js
_Child2.scss
helpers
util1.js // with a single default export
util2.js // with a single default export
_MyComponent.scss
MyComponent.js
MyComponent.spec
Where child components are (or should) only be pulled into this component. Ie. they shouldn't be used by other components.
This hashnode article also has a great structure if you are using redux as well: hashnode.com/post/tips-for-a-better-redux-architecture-lessons-for-enterprise-scale-civrlqhuy0keqc6539boivk2f
It seems that you are missing the concept of components vs containers (or dumb components vs smart components, as some like to name it). Basically, it is a good practice to apart your business logic from you pure presentational components.
Have a look at Presentational and Container Components, by Dan Abramov.

Reactjs - How to make components aware of the current view state?

Tools I'm Using: Reactjs 0.14.7, react-router 2.0.0 (Flux Pattern)
Note: I tagged Redux, just cause I got a hunch(I haven't used it) that what I'm experiencing might be one of the reasons people rave about it.
I understand that react-router already manages which parts of the
component tree are currently in view and renders the components based on the state of the current view tree.
Question:
But what if, based on the components in view, one component needs to know what other components are also in view and behave differently depending on what other components are in view(the view state)? What strategy would you suggest to allow components to be aware of the other components in view?
My Current Solution:
I currently am trying to use the URL to infer this global state, and even parsing it and putting it into a store in order for components to be aware of the view state by listening to changes from that store.
My Issue With This Solution:
In a nutshell managing that view state with a store becomes a highly entangled process with extra actions sprinkled all over the code.
1) Actions must be called for any user event that change the route.
2) Action need to be fired when navigating outside of components(I think its much cleaner to keep action firing in components(feel free to debate that one).
3) You must also consider the back button(currently using react-router onEnterHooks to catch when that happens).
Yet I really like the concept of encapsulating the view state because I can imagine that it creates a nice mental model and also smarter components, but just parsing the current URL and using a utility file to determine the current view state when needed, seems like a much easier/cleaner solution to manage then a store that contains the current view state.
Components should never need to know what other components are being rendered, that's one of the fundamental concepts of React. You're trying to extract the "view state" from your component tree, when your component tree should be determined by your state. If you're already using Flux, you need to keep that information in the store, where it will be made accessible to any component that subscribes.
Flux isn't about making development easier or faster for an individual, it's about enabling practices that make it easier to keep a mental model of what an application is doing. This might come at the expense of some simplicity.
Redux is a refinement of Flux that combines the multiple stores that can be subscribed to individually with a single large state tree, with different parts of the tree created by different "reducers" -- functions that take a state and an action and return a new state. It is exactly "a store that contains the current view state." What you describe is also a pretty good description of the type of development common in hacked together jQuery applications, the type of development React seeks to avoid.
I think the core of your misunderstanding falls into how React component's should be layered. It's a tricky topic, and re-aligning your thought process to accurately understand what is a state vs. prop in your model, is a unique challenge.
But the solution to this problem you are facing is simply to order your components more 'correctly'.
At a high level, each component should only care about the props that are passed to it, and not about anything else whatsoever. However, which props are passed are determined by it's parent Component. As a result, that parent can make those decisions, which then have an end result in the child.
As a simple but practical example;
var Parent = React.createClass({
funcA: function(){
this.setState({propB: 'something new!'});
},
render: function(){
return (
<div>
<ChildA propA={this.state.propA} funcA={this.funcA} />
<ChildB propB={this.state.propB} />
</div>
);
}
});
With this layout of concerns, ChildA is capable of handling user input, passing it to funcA which then impacts ChildB. But all of this happens without the Child components knowing anything about one another whatsoever.

ReactJS Modal Component

How do you create a ReactJS component that reaches multiple levels up the component/DOM hierarchy?
A good example of this is a Modal. I want to trigger and control the modal from a child nested way down in my app, but a Modal requires that the DOM be much higher, most likely all the way up as a child of the document body.
I'm considering a "portal" pattern, as described here: https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/05-wrapping-dom-libs.md#portals
FakeRainBrigand even wraps the pattern up nicely in a mixing in this post: https://stackoverflow.com/a/26789089/586181
This feels like a hack to me. Great if you want to use a non-react library like jquery-ui, but without that need breaking out of react just to render a react component somewhere else in the DOM seems like overkill. Is there a more "React" way of achieving this?
Thanks
I'll leave this best to the react documentation. If you must have buried React elements that need to communicate with other elements outside of their Parent Child or possibly even grandparent than see the below.
For communication between two components that don't have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
https://facebook.github.io/react/tips/communicate-between-components.html
I've written a library to help with this. I avoid the DOM insertion hacks used by Portal strategies out there and instead make use of context based registries to pass along components from a source to a target.
My implementation makes use of the standard React render cycles. The components that you teleport/inject/transport don't cause a double render cycle on the target - everything happens synchronously.
The API is also structured in a manner to discourage the use of magic strings in your code to define the source/target. Instead you are required to explicitly create and decorate components that will be used as the target (Injectable) and the source (Injector). As this sort of thing is generally considered quite magical I think explicit Component representation (requiring direct imports and usage) may help alleviate confusion on where a Component is being injected.
You can completely use my library to bind a ModalComponent to a root level component that you decorate with the Injectable helper. I plan on adding an example of this use case soon. It even supports natural props pass throughs, and all the various component types i.e. stateless/class.
See https://github.com/ctrlplusb/react-injectables for more info.

Resources