React: how to connect reusable components with usual dumb components - reactjs

When I develop a React-based web-app, I often separate components into smart and dumb and also into reusable and custom.
Reusable components can be self-sufficient, such as e.g. <RedButton> or <CustomSelect> but they can also be middleware components, such as <FluxStoreBinder>. A middleware component renders its children while adding some functionality to them, usually such as subscribing-reading to/from a Flux store, or wrapping into some other stateful thing. However, some extra work is needed to connect a reusable smart middleware component to a dumb component because their props won't likely match. E.g. a <FluxStoreReader> may "return" a property named data, while a child of type <ToDoList> expects toDoItems.
The question which I want to ask is how to tell a middleware component which content to render in which way. What is the proper and recommended approach? Currently I've seen 3 ways of telling a middleware component how to render its children:
By providing a function through props, such as render={({arg1}) => <Child prop1={arg1}/>}. The features are: you can access own state/props/etc within this function; you can process and re-map props; you can specify which child to render depending on a condition; you can set needed props to the child without having to proxy through the middleware component.
By returning React.cloneElement(children, props) while providing a function to remap props.
By rendering React.cloneElement(children, props) and proxying received props down to the child. Pure component approach, no callbacks. This one don't have the features/flexibility of the above 2, and also requires some extra work: you need another middleware between your middleware and its child to re-map the props.
The fourth option suggested by Mike Tronic is to use higher-order components, which are basically component factories, where one of the required arguments is a child component class. It's almost the same as #3 - but you can't even change the type of the child once you've run the factory.
Which approach did you choose for your application? Why? Please share thoughts.
Would be great to hear a React guys' opinion.

check https://www.youtube.com/watch?v=ymJOm5jY1tQ
http://rea.tech/reactjs-real-world-examples-of-higher-order-components/ and
http://www.darul.io/post/2016-01-05_react-higher-order-components
What are Higher Order Components?
A Higher Order Component is just a React Component that wraps another one.
This pattern is usually implemented as a function, which is basically a class factory (yes, a class factory!), that has the following signature in haskell inspired pseudocode
hocFactory:: W: React.Component => E: React.Component
Where W (WrappedComponent) is the React.Component being wrapped and E (Enhanced Component) is the new, HOC, React.Component being returned.
The “wraps” part of the definition is intentionally vague because it can mean one of two things:
Props Proxy: The HOC manipulates the props being passed to the WrappedComponent W,
Inheritance Inversion: The HOC extends the WrappedComponent W.
We will explore this two patterns in more detail.
What can I do with HOCs?
At a high level HOC enables you to:
Code reuse, logic and bootstrap abstraction
Render Highjacking
State abstraction and manipulation
Props manipulation
We will see this items in more detail soon but first, we are going to study the ways of implementing HOCs because the implementation allows and restricts what you can actually do with an HOC.

Related

Are Pure, Presentational and Dumb Components all the same thing?

Are Pure, Presentational and Dumb Components all the same thing?
Basically, stateless functional components, which are concern about How Look and not How Work, and are never connected to Redux store?
At a fundamental level, any function that doesn’t alter input data and that doesn’t depend on external state (like a database, DOM, or global variable) and consistently provides the same output for the same input is a pure functions
const add = (a, b) => a + b //pure function
In React, a presentational component or a dumb component is a component that just renders HTML. Their only responsibility is to present something to the DOM.These components are often just Javascript functions. They don’t have internal state to manage. They wouldn’t know how to change the data they are presenting if they were asked. Ignorance is bliss.
In a Redux-powered app, such components do not interact with the Redux store.
However, they accept props from a container component (smart components).
Class-based components that have their own state defined in their constructor() functions
class App extends Component {
constructor(props){
super(props);
this.state = {pictures : []};
}
}
Because container components have the burden of being smart, they are the ones that keep track of state and care about how the app works. They also specify the data and behavior a presentational components should render by passing it down to them as props.If the presentational component has any interactivity — like a button — it calls a prop-function given to it by the container component. But the container component is the one to dispatch an action to the Redux store.

React Redux and inheritance

I'm really wondering why there is nothing about Redux and how to deal with inheritance. If I have a base component:
class BaseComponent extends Component{
}
then all other components are extending BaseComponent:
class Todo extends BaseComponent {
}
I want to simply connect the BaseComponent to it's own reducer so every other component which extends it, also can access the same props and states.
Unfortunately can't find any documentation out there. I have no idea if this is a right concept or not.
With react you usually will not further inherit from your own components.
Here is a quote from the official docs on Composition vs Inheritance:
At Facebook, we use React in thousands of components, and we haven’t found any use cases where we would recommend creating component inheritance hierarchies.
Props and composition give you all the flexibility you need to customize a component’s look and behavior in an explicit and safe way. Remember that components may accept arbitrary props, including primitive values, React elements, or functions.
If you want to reuse non-UI functionality between components, we suggest extracting it into a separate JavaScript module. The components may import it and use that function, object, or a class, without extending it.
That being said, if you still want to deviate from the recommended way and have a base component for shared functionality, it is possible. You are still on the "safe side" (i.e. it will most likely not cause too much confusion or trouble) if you (1) reduce the functionality in your base to the least common denominator needed by most of its children (2) do not keep any shared state in your base component (3) do not use arrow functions in your base component and if you (4) make sure to keep your lifecycle methods and connect in your child components to avoid unexpected behaviours.
Performing a connect in your base class, as you are planning to do it, would be problematic as connect returns a newly wrapped component which acts as an owner of your actual BaseComponent (see how connect works). Therefore, you will lose the ability to access your class methods, in your ChildComponents. Also, most likely other bad things will happen because you now independently inject and manage state and lifecycles on two levels (child and base). – Therefore, your best shot, when using a custom BaseComponent, would be to not put connect in your parent but let the child handle the connect.
Here is also a blog article by Dan Abramov worth reading that discusses the question of inheritance in react. His main concerns are that multi-level hierarchies are harder to refactor, name clashes will arise if a parent class later adds methods with names that some child class already uses, sharing logic between child and parent methods makes it harder to understand the code. Overall he suggests to rely on functional programming style.
So what are my recommendations for React components?
You can use class in your JS if you don’t inherit twice and don’t use super.
Prefer to write React components as pure functions when possible.
Use ES6 classes for components if you need the state or lifecycle hooks.
In this case, you may only extend React.Component directly.
Give your feedback to the React team on the functional state proposals.
Generally speaking, whether or not hierarchies are good in OOP programming is a highly debated field.
Inheritance is not widely preferred and encouraged in React and hence you don't find much documentation about this online. A better way to achieve what you want is to export a container which you can then wrap as a HOC to any component you wish to use it for
connectContainer.js
const mapStateToProps = state => {
return {}; // return data you want from reducers
}
const mapDispatchToProps = {}; // define action creators you want to pass here
export default connect(mapStateToProps, mapDispatchToProps);
Now in any component you wish to use the same container properties, you can use them like
import connectHOC from './connectContainer';
class Todo extends React.Component {
}
export connectHOC(Todo);

Will using the React props spread operator significantly slow-up my application?

When passing props down into a React component I am currently of doing this:
<MyComponent
{...this.props}
foo=foo
bar=bar
/>
foo and bar are props that I know MyComponent will need. However, in most cases MyComponent also has components within it that need props from higher components, hence I use the {...this.props} operator to pass them forward. Should I be doing this, or should I be listing out exactly the props that the child components of MyComponent will need?
You should use a state management like Flux, Redux or Mobx (i think, haven't used Mobx at all) to combat this problem of passing props through multiple levels without the intermediate components needing them.
You should be passing only the props exactly needed down to the child. I read a great post on github about this but can't find it.
It's just hard to manage when your app grows and it's really an abuse of the Es6 spread syntax operator (i.e it makes it easy short term to pass props down, but long term you still have the problem, you are just masking it). Not sure if it slows down application but it will re-render all child components again if the prop changed which is unnecessary.
For example when using Redux you can "connect" components to a global state (think databases) and pass them through as props for whichever components you want and bypass components having to forward props to child components.
It's hard at first to learn but 1000% worth it.
You should pass in only the props needed, or implement a container component that only passes in the props needed. Or you can implement shouldComponentUpdate on your component. The easiest way to get performance is to only pass in the required props though.

Explanation for wrapping React HOC components with scalajs-react

I am trying to understand #trepidacious's scalajs-react wrapper for this HOC react component.
1a) Why is the type of the wrapped component here ReactComponentC[P,_,_,_] ?
1b) Why is the return type of the component ReactComponentU_ ?
def wrap[P](wrappedComponent: ReactComponentC[P,_,_,_]): Props => P => ReactComponentU_ = {
2) Why is the factory function passed to SortableElement here ?
val componentFactoryFunction = js.Dynamic.global.SortableElement(wrappedComponent.factory) ?
Does not SortableElement take a Component ?
3) Why are the wrapped props passed like this ?
"v" -> wrappedProps.asInstanceOf[js.Any]
What is the reasoning behind this line ?
Where is that magical v is coming from ? Is it from scalajs-react or from react-sortable-hoc ?
4) What is the reasoning behind this wrapper ? If I want to write a wrapper for another HOC component, what should be the general recepie for that ?
There are quite a lot of parts here, but I've put together some links working from the lowest level to the highest while covering the questions.
The first and most important definitions are of React Components and React Elements. This page has an in-depth explanation - I recommend completely skipping the "Managing the Instances" section since it muddies the waters by describing a traditional UI model while using terms differently to the way they are used in React. In summary my understanding is that:
A React Component is a general concept that can be implemented in multiple ways. However it is implemented, it is essentially a function from props (and optionally state) to page contents - a renderer.
A React Element is a description of page contents, representing a particular rendering of a Component.
React components and props docs describe the two ways of defining a React component, the first one is a function from props to a react element, this is the one we're interested in. The React.createFactory docs then confirm that we can pass such a function to createFactory. As far as I can tell this exists in order to adapt from the multiple ways of defining a React Component (by subclassing React.Component or React.PureComponent, by using React.createClass, or by a function from Props to ReactElement) to a way of rendering props to a ReactElement. We can see something about this by looking at this gist introducing React.createFactory in React 0.12 - essentially they wanted to introduce some abstraction between the class used to define a React Component and the eventual function from props to React Elements that is used when rendering, rather than just letting the class render props directly.
Next we have a minor wrinkle - React.createFactory is flagged as legacy in the docs. Luckily this isn't a major issue, again as far as I can tell React.createFactory(type) just produces a function f(props) that is identical to React.createElement(type, props) - we are just fixing the type argument in React.createElement. I've tested this in the react-sortable-hoc wrapper, and we can use createElement instead of createFactory:
val componentFunction = js.Dynamic.global.SortableContainer(wrappedComponent.factory)
(props) => (wrappedProps) => {
val p = props.toJS
p.updateDynamic("v")(wrappedProps.asInstanceOf[js.Any])
React.asInstanceOf[js.Dynamic].createElement(componentFunction, p).asInstanceOf[ReactComponentU_]
}
We're now nearly at question 2). If we look at the source for SortableElement we can see that the sortableElement function accepts a WrappedComponent argument - this is used to create another React Component, via the "subclass React.Component" approach. In the render function of this class, we can see that WrappedComponent is used as a React Component, so we know that it is indeed a component, even without a static type :) This means that WrappedComponent needs to be something accepted by React.createElement, since this is what a JSX component use desugars to.
Therefore we know that we need to pass to the sortableElement function something that is usable as a React Component in javascript React.createElement function. Looking at the scalajs-react types doc we can see that ReactComponentC looks like a good bet - it constructs components, presumably from props. Looking at the source for this we can see that we have two promising looking values - reactClass and factory. At this point I realise that the code is probably using the wrong one - I've tried replacing .factory with .reactClass and this still works, but makes much more sense since we have the comment to tell us that it gives Output of [[React.createClass()]], which is one of the options for a valid React Component. I suspect that factory also works by essentially wrapping up the provided component in createFactory twice, since the output of createFactory is also usable as its input... I think given this correction we've answered question 2 :) This also pretty much answers question 1a) - ReactComponentC is the scala trait that gets us the .reactClass val we need for a scala-defined React Component. We only care about the type of props it uses (since we have to provide them), hence the P. Since scala IS typed we know that this is what we get from building a scala React Component in the normal way (at least for components I've tried).
On question 1b), I found the type ReactComponentU_ from code like the ReactCssTransitionGroup facade in scalajs-react Addons and the scalajs-react-components notes on interop, which shows wrapping of a non-HOC component. Looking at the type itself we can see that it extends ReactElement, which makes sense - this is the expected result of rendering a React Component. In our wrap function in the SortableElement and SortableContainer facades we are producing (eventually) another function from props to ReactElement, just one that jumps through a few hoops to get there with the HOC approach. I'm not sure why ReactComponentU_ is used instead of just ReactElement, I think this is to do with tracking the state of components through the type, but the code still compiles if I return ReactElement, which is odd.
Question 3) is much easier - scalajs-react works with Props that can be Ints, Longs etc. but in Javascript these are not objects. To make every scalajs component's props be an object, scalajs-react wraps them in an object like {"v": props}, and then unwraps again when they are used. When we wrap a Scala React Component using the HOC, we need to get that wrapped component's props to it somehow. The component produced by the HOC function (the "wrapping" component, SortableElement or SortableContainer) does this by expecting its own props to already contain the wrapped component's props as fields, and it then just lets these flow through to the wrapped component, for example in SortableElement's render:
<WrappedComponent
ref={ref}
{...omit(this.props, 'collection', 'disabled', 'index')}
/>
this.props is passed through to the wrapped component. Since the wrapped scala component requires a "v" field with the scala props object in it, we need to add this to the wrapper component's props. Luckily this field will then pass through unaltered to be interpreted later by the scala component. You won't see the "v" field since scalajs-react will unwrap it for you.
This does raise a problem when wrapping some other HOCs - for example ReactGridLayout's WidthProvider measures the wrapped component's width and passes it through in the props as {"width": width}, but unfortunately we can't see this from scala. There may well be some workaround for this.
That covers the details and references for the parts of the HOC wrapping, but actually the process is pretty easy (providing you don't want to access props "injected" into the wrapped component):
Make a scala object for the facade to organise the code.
Work out what props are required by the wrapper component. For example in SortableElement this is index, collection and disabled. Make a Props case class with these fields, in the facade object.
Write a 'wrap' function in the facade object. This does the following:
Accepts a wrappedComponent: ReactComponentC[P,_,_,_] and passes it to the javascript HOC function (e.g. SortableElement) to produce a new React Component.
Builds a javascript props object with the wrapper component's props AND the magic "v" field with the wrapped component's props.
Uses javascript React.createElement function to produce a ReactElement that renders the wrapped component, and casts this to ReactComponentU_.
Note that at stage 5 we need to convert from our Scala Props case class (the wrapper component's props) to a plain javascript object that can be understood by the HOC. The wrapped component's props just go straight into the "v" field without conversion, just casting to js.Any.
The code I wrote for SortableElement and SortableContainer splits this up a little so that wrap returns a curried function that accepts the props for the wrapper component and produces another function from the wrapped props to the final React element. This means that you can provide the wrapper props once and then use the resulting function like a normal component in your Scala render code.
I've updated the SortableElement facade with the improvements above, and this is pretty much a minimal example of a HOC facade now. I would imagine other HOCs will look very similar. You could probably abstract some of the code for the purposes of DRY, but actually there's not really a lot there anyway.
Thanks for the questions and for helping work this out - looking back through the process and particularly your question on .factory has left me more confident that this is now working the right way (with the changes described).
I don't have all the answers but my understanding is that the author of scalajs-react uses lots of types to prevent errors during construction of components as well as during the lifecycle of the components once constructed. He uses naming conventions with suffixes and letters to separate the types which make sense but can be daunting at first.
1a) ReactComponentC is a constructor for a component (C as in Constructor).
1b) ReactComponentU_ represents an unmounted native (JavaScript) React component.
3) I think, looking at the scalajs-react source, that yes, "v" is a magic key name. There is (was?) also some notes in the source code to the effect that this is not ideal ;)
There is a plan to simplify scalajs-react's types in a new version.

Difference between using a HOC vs. Component Wrapping

I just checked out HOC's in React. They are pretty cool. However, doesn't simply wrapping a component achieve the same result?
Higher Order Component
This simple HOC passes state as properties to the ComposedComponent
const HOC = ComposedComponent => class extends React.Component {
... lifecycle, state, etc;...
render() {
return (<ComposedComponent {...this.state} />);
}
}
Component Wrapping
This component passes state as properties to the child component
class ParentComponent extends React.Component {
... lifecycle, state, etc;...
render() {
return (
<div>
{React.cloneElement(this.props.children, { ...this.state })}
</div>
);
}
}
Although usage is slightly different between the two, they both seem to be equally as reusable.
Where is the real difference between HOC's and composing components via this.props.children? Are there examples where you can only use one or the other? It is a better practice to use HOC's. Are these just choices that you have where you get to pick your preferred flavor?
Higher-Order Components (HOC) and Container Components are different. They have different use cases and solve similar, but different problems.
HOC are like mixins. They are used to compose functionality that the decorated component is aware of. This is opposed to Container Components that wrap children and allow the children to be dumb (or not aware of the Container's decorated functionality).
It is true when transferring props, that Containers can add functionality to their children. But, this is usually in the form of props being passed down to the children. In Containers, this is also awkward because of the limitation that you cannot simply add props to an already created Element:
So, if you wanted to add a new prop to a child from this.props.children, you would have to use cloneElement. This is not as efficient because it means you have to re-create the elements.
Also, HOC is simply a way (factory) for creating Components. So, this can happen outside the render.
I just wanted to add that when you need to dynamic higher order components the Container approach works better.
If you e.g have 4 elements to render that could have a HOC defined, you would like to create the Higher Order Component inside render, but since calling higher order components inside render causes the <HigherOrderComponent/>'s to remount on every render this becomes a very bad Idea.
This is documented here; https://github.com/facebook/react/blob/044015760883d03f060301a15beef17909abbf71/docs/docs/higher-order-components.md#dont-use-hocs-inside-the-render-method.
But in general I would go for the HOC approach.

Resources