Why Reactjs has to reuse code in HOC? - reactjs

All I want is to run a piece of javascript code to query back-end GraphQL server. Why do I have to wrap my query in a HOC component? Like it says in this document.
import { Query } from "react-apollo";
import gql from "graphql-tag";
const ExchangeRates = () => (
<Query
query={gql`
{
rates(currency: "USD") {
currency
rate
}
}
`}
>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.rates.map(({ currency, rate }) => (
<div key={currency}>
<p>{`${currency}: ${rate}`}</p>
</div>
));
}}
</Query>
);
It looks like a very clumsy awkward solution? Why it has to be this way? Does it make things easier or more difficult? What is the philosophy behind it?
Update:
One thing trouble a lot is: I just want to make an API call, which is not visible, why do I have to render a tag inside render() function? API call are not supposed to be visible at all. This twist make me feel this whole HOC thing is a hack, bogus. What do you think?

They use Render Prop Pattern because of it's highly declarative nature as outlined here
This encapsulation makes composing your Query components with your presentational components a breeze
Now about the Render Prop itself, as per official react docs
The term “render prop” refers to a simple technique for sharing code between React components using a prop whose value is a function.
A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
As described here this technique is React's favoured way of handling cross-cutting concerns.
Components are the primary unit of code reuse in React, but it’s not a always obvious how to share the state or behavior that one component encapsulates to other components that need that same state.
So with render prop you put out only the public outcome of your encapsulated state that you want to share with other components.
render prop is not HoC, but is an alternative to it, that was recently embraced by the react team itself.

Related

Need a clearer explanation how to avoid infinite re-rendering with React hooks

Not so fluent with React hooks, used plenty of class components before, hope you'll be forgiving.
The current code causes infinite re-rendering, and I think I understand why - the entire function body is being called on re-render.
const NavTabs = () => {
const classes = useStyles();
const [categories, setCategories] = React.useState();
const axiosPromise = getRequest(consts.categoriesURL);
axiosPromise.then(data => {
setCategories(data.value);
})
return (
<div className={classes.root}>
<AppBar position="static">
</AppBar>
{categories && <DynamicTabs categories={categories}/>}
</div>
);
}
I guess I could do something like if (!categories) { const axiosPromise [...] and so forth, i.e. do the http request only if categories haven't been populated yet. I guess this could also be solved by useEffect? Or wrapping the hook in an internal function?
I guess my real question is - why is React re-rendering the entire function body? Shouldn't it re-render only the return function? And then what is the point of using hooks that will be re-run on every render?
Compared to class components - shouldn't the code in the function body be equivalent to the constructor code in class components, and the return function - equivalent to the render method?
I guess I could do something like if (!categories) { const axiosPromise [...] and so forth, i.e. do the http request only if categories haven't been populated yet. I guess this could also be solved by useEffect? Or wrapping the hook in an internal function?
Yes, useEffect is the way to go here. Making a request and setting the result as state are side effects should only be run once in your case. We can achieve that easily with useEffect.
I guess my real question is - why is React re-rendering the entire function body? Shouldn't it re-render only the return function? And then what is the point of using hooks that will be re-run on every render?
React has no way to split a js function and only re-render the return. The function is atomic and must be completed. That is what hooks are for. React controls when hooks are ran so it can do fun stuff like batch state updates, ignore outdated effects and prioritise high priority work like animations.
Compared to class components - shouldn't the code in the function body be equivalent to the constructor code in class components, and the return function - equivalent to the render method?
The functional component is equivalent to the render method of a class component. They are called in a similar way. All the other lifecycle methods are replaced by hooks.
I recommend the react docs are great place to start and Dan Abramov has a great deep dive on hooks.
Yes, getRequest is being invoked each render cycle which sets some state and triggers a rerender. Placing it in an effect hook with a dependency array is likely the best solution. What dependencies you define will dictate when getRequest can be invoked.
Why is React re-rendering the entire function body?
The entire function body needs to run in order to determine the return value.
And then what is the point of using hooks that will be re-run on every render?
Hooks are run on every render, in the same order they are defined, but depending on dependencies may not invoke a callback. Hooks are what give functional components so much viability and sense of component lifecycle, to nearly be equivalent to class-based components in functionality. In most cases, you can completely convert a class-based component to a functional one and not drop any functionality.
Compared to class components - shouldn't the code in the function body be equivalent to the constructor code in class components, and the return function - equivalent to the render method?
It is more accurate to think of the entire functional components definition as the class-based render function, which can contain some logic and returns computed JSX to render to the DOM.
Example Solution:
const NavTabs = () => {
const classes = useStyles();
const [categories, setCategories] = React.useState(); // <-- no initial state!
useEffect(() => {
getRequest(consts.categoriesURL).then(data => {
setCategories(data.value); // <-- will update state and trigger render
});
}, []); // <-- empty dependency is run once on component mount
return (
<div className={classes.root}>
<AppBar position="static">
</AppBar>
{categories && <DynamicTabs categories={categories}/>}
</div>
);
}
To answer "why react is running the entire function" the answer is that javascript functions work that way: you always have to run the whole thing, they don't stop in the middle*. I understand what you are thinking here, if you are used to class components: don't I have a constructor section and a render section? and the answer is: not really if you are using function components. You only have render. But hooks are magic, and they let you pretend to have two parts.
Hooks know when they are called, and assuming you always call them in the same order, the can keep track of state outside the render function. so the way the work is sorta like this:
React detects a function component and creates or re-uses an existing rendering context for that component. This is where the hook information lives.
React calls your function component and it starts running.
You call hooks within your function component. These check what the current rendering context is, and save/get relevant information from that context. In a sense the rendering context is a "global" variable.
You do whatever else you want within the function, and eventually return a component tree (JSX) or null.
react then (eventually) updates the DOM to match what you returned, and saves the changes to the rendering context, so the next time render is called, it can re-use the context.
The magic is that the rendering context can do fancy things with hooks, like only run them once, always return the same value from a hook, or any other number of things. But in a sense, the component "class" becomes the react-internal rendering context that hooks know how to access.
Here is an example of the useState hook implemented in a class component: (You wouldn't ever need to do this, but it's an example of how hooks work).
class FakeHook extends React.Component {
constructor(...args) {
super(...args)
this.state = {}
this.useStateCalls = 0
}
useState(defaultValue){
const currentRenderContext = this.state
let value = defaultValue
const currentStateKey = `useState${this.useStateCalls}`
if (currentStateKey in currentRenderContext) value = currentRenderContext[currentStateKey]
this.useStateCalls++
return[value, (newValue) => this.setState({[currentStateKey]: newValue})]
}
render(){
this.useStateCalls = 0
let [fooState, setFoo] = this.useState("foo default")
let [barState, setBar] = this.useState("bar default")
return(
<dl>
<dt>Foo state</dt>
<dd>
<strong>Value:</strong>
<div>{fooState}</div>
<button onClick={(event) => {event.preventDefault(); setFoo(`foo updated at ${new Date().toLocaleString()}`)}}>Update Foo</button>
</dd>
<dt>Bar state</dt>
<dd>
<strong>Value:</strong>
<div>{barState}</div>
<button onClick={(event) => {event.preventDefault(); setBar(`bar updated at ${new Date().toLocaleString()}`)}}>Update Bar</button>
</dd>
<dt>Render context state:</dt>
<dd><pre>{JSON.stringify(this.state)}</pre></dd>
</dl>
)
}
}
ReactDOM.render(<FakeHook/>, document.getElementById('main'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main id=main>loading or error occurred...</main>
Notice that state is stored based on the order the hook is called inside render. In real hooks, the render context is stored somewhere other than this.state, but hooks know how to get it, and you don't really care. Also, this is just an example, real hooks work slightly differently, but the concept is the same.
*: async functions and generators don't run all at once, and instead return a special object that lets the function run in multiple steps, waiting or pausing on await or yield.

Different ways to query with react-apollo

We started using the react-apollo#2.1 in one of our react-redux application and we are trying to replace most of the redux stuff with graphql. So we started using the <Query> component and converted some pages to use the <Query> component. But in some pages, we have some existing logic which uses react lifecycle events like componentWillReceiveProps and if we used the <Query> component then those events won't get fired and if we use HOC type querying like below then the lifecycle events get fired and we will get the data in the props
export default graphql(GET_APP_INFO, {
options: ownProps => ({
variables: { appName: ownProps.params.app }
}) })
My understanding is that the component is the latest way to query and HOC is the old way which may get deprecated, also I saw some other way to query with withApollo() like below.
this.props.client.query({
query: gql...,
variables: { ... },
});
So I am looking for suggestions on when to use these different types of querying patterns to get the data
The Query component and the graphql HOC have the same basic functionality, so there shouldn't be a distinction from that perspective. Your example of the Query component not running lifecycle methods, you could move the Query component up one level out of the component, and it would work exactly the same. So something like this:
const CompQueryWrapper = () => {
return (
<Query ...>
{({ data, loading, error }) => <CompWithLifecycle data={data} />}
</Query>
}
You also might be able to move the lifecycle logic down a level. reactions/component can sometimes be handy in this case, when you just want something to trigger on a props change but don't want to go through the ceremony of making a new class component.
So yeah, for your specific situation, my recommendation would be to move the Query up so that it triggers the lifecycle or move the lifecycle logic down so it can be triggered by the Query result.
In general, the two components that I use for making queries are
Query Component
ApolloConsumer (it's basically just a render-prop version of withApollo)
If I can use the Query component, I use the Query component. It works for most situations. The use-case for ApolloConsumer for querying is when you don't want to immediately trigger a query. For example, say you have a form that requires some info from the user and then gets some data based on that input. It's not a mutation, since we're not changing any data, but we don't want it to fire immediately either like the Query component does. In this case, use ApolloConsumer to get the client instance, and fire the query using client.query.
if you want use React-Apollo and run Query Dynamic , for example inside ReactLifeCycleMethod or in any other method ( for some case , when any Event listener trigger ) , you cane use Client for access Query or Mutation
React-Apollo have Consumer , with React Context API
in Top Level of your Application you implement ApolloProvider like this
<ApolloProvider client={client} >
< App />
</ApolloProvider>
and now you have access client
you can create Query with Client
client.query()
or
client.mutate()
and if you want use client in other component you must use ( like react new Context API)
class App extends React.Component {
render() {
return(
<ApolloConsumer >
{ client => {
<MyComponent accessClient={client} />
} }
<ApolloConsumer>
)
}
}
now in you can access client as props
class App extends React.Component {
componentDidMount() {
this.props.accessClient.query( ... )
}
render() {
return(
....
)
}}
https://www.apollographql.com/docs/react/essentials/queries.html#manual-query

What's render props, how is it different from high order components?

It seems render props have not get enough traction so far, however, it's widely used by prestigious react libraries, like react-router 4, react motion etc. And react site also have a dedicated section for it, any reason for this emerged pattern, how is compared to commonly known HOC (high order component) pattern?
Leave an answer for my research, different answers & discussions are highly welcome!
HOC borrows the concept from High Order Function:
a higher-order function (also functional, functional form or functor) is a function that does at least one of the following:
takes one or more functions as arguments (i.e., procedural parameters),
returns a function as its result.[disputed – discuss]
HOC
A higher-order component (HOC) is an advanced technique in React for reusing component logic.
Originates from this Gist.
This pattern is about STATIC composition. Core/reusable logic are encapsulated in the HOC, while leaving the moving parts to the component.
Use withRouter from react router as an example:
withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
// This gets around shouldComponentUpdate
withRouter(connect(...)(MyComponent))
Now you get an enhanced MyComponent back which has the props of { history, match, location, ...connectProps, ...ownProps } passed by the router HOC.
A common approach is to
compose(
connect( ... ),
enhance( ... ),
withRouter( ... ),
lifecycle( ... ),
somethingElse( ... )
)(MyComponent);
The great part is that you can infinitely compose those HOCs with a compose utility to get a final enhanced version of your component, and your component will get knowledge about redux store, react router etc injected from the new component returned by HOC.
The downside of the approach is that:
The behavior of the component is defined before runtime thus lost the power of react's rendering lifecycles, say you can't do something like:
compose(
this.state.shouldConnect && connect( ... ),
this.state.shouldEnhance && enhance( ... ),
this.state.shouldWithRouter && withRouter( ... ),
...
)(MyComponent);
since state/props is not available before your code runs.
Indirection & Naming collisions.
using a HOC with ES6 classes poses many of the same problems that mixins did with createClass, just re-arranged a bit.
HOCs introduce a lot of ceremony due to the fact that they wrap components and create new ones instead of being mixed in to existing components.
Render Props
A render prop is a function prop that a component uses to know what to render.
First adopted by react-motion, early seen in Dan's Gist few weeks before first commit of redux.
This pattern is about DYNAMIC composition. Core/reusable logics stays in the component while the moving parts get passed as a callback prop.
You can create HOCs through render props.
Still use withRouter as an example:
const withRouter = Component => {
const C = props => {
const { wrappedComponentRef, ...remainingProps } = props;
return (
<Route
render={routeComponentProps => (
<Component
{...remainingProps}
{...routeComponentProps}
ref={wrappedComponentRef}
/>
)}
/>
);
};
...
return hoistStatics(C, Component);
};
While the opposite is not true.
<Connect render={connectPropsMergedWithState => {
<Enhance render={enhancePropsMergedWithState => {
<WithRouter render={routerPropsMergedWithState => {
<Lifecycle render={lifecyclePropsMergedWithState => {
<SomethingElse render={somethingElsePropsMergedWithState => {
...
}/>
...
}/>
...
}/>
...
}/>
...
}/>
Though it might look not so good, it has lots of gains.
It has better explicitness, since we can see what's exactly passed as parameter to the render props.
Because of 1, it saves us from potential props collisions.
It's dynamic, we can pass whatever we like (including state/props) to render props.
The commonly known downside is performance optimization is tricky, since what props to receive is deferred to runtime. And it's probably not a good idea to do any premature optimization, but that might be totally another topic.
If you agreed upon the direction move of react router from 3 to 4, render props might be your jam.
References:
https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce
https://reactrocket.com/post/turn-your-hocs-into-render-prop-components

Prevent Re-Render when React Element passed as Prop

In my React app, I am using a few libraries (i.e. Material UI and React Intl) to pass React elements as props from higher-level components down to "dumb components" that have one job: to render.
Smart component:
import ActionExplore from 'material-ui/svg-icons/action/explore';
import { FormattedMessage } from 'react-intl';
export class SmartComponent extends Component {
render() {
return (
<div>
<DumbComponent
text={<FormattedMessage id="en.dumbComponent.text" />}
icon={<ActionExplore/>}
/>
<AnotherDumbComponent {props.that.are.changing} />
</div>
);
}
}
Dumb component:
import shallowCompare from 'react-addons-shallow-compare';
export class DumbComponent extends Component {
shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
render() {
return (
<div>
<h1>{this.props.text}</h1>
{this.props.icon}
</div>
);
}
}
The benefit of doing this, is that the DumbComponent does not need to know anything about application logic (material ui, internationalization, etc.). It simply renders, leaving SmartComponent to take care of all the business logic.
The downside I am encountering with this approach is performance: DumbComponent will always re-render, even when AnotherDumbComponent's props change instead of its own, because shouldComponentUpdate always returns true. shouldComponentUpdate is unable to do an accurate equality check between React elements in the above example.
How can React elements be equality-checked in shouldComponentUpdate? Is this too costly to perform? Is passing React elements as props to dumb components a bad idea? Is it possible to not pass down React elements as props, yet keep components dumb? Thanks!
Whether it is performant or not is going to depend on your use case. As a rule of thumb, I think this kind of logic is best used when you expect user input to only impact children of the "dumb component", rather than it's peers.
As an example, Material-UI's Dialog has almost identical structure to what you suggest for it's action buttons and title. (https://github.com/callemall/material-ui/blob/master/src/Dialog/Dialog.js#L292). But it works well in that case because those elements are on the modal, which itself doesn't modify unless you are opening or closing it.
As another potential workaround, what if you passed in the objects needed to create the children elements, without passing in the entire element? I haven't tried this, so I'm not sure how well it will work, but it might be worth a try. Something to the extent of;
<DumbComponent
textComponent={FormattedMessage}
textProps={{id: "en.dumbComponent.text"}}/>
//In DumbComponent;
render(){
return (
<div>
<h1>
<this.props.textComponent {...this.props.textProps}/>
</h1>
</div>
);
}
Might give you some more concrete things to play around with when determining if you should update or not.
I solved this by converting these plain React elements into Immutable.js maps, and passing those as props instead.
This article was very helpful: https://www.toptal.com/react/react-redux-and-immutablejs
Immutable.js allows us to detect changes in JavaScript objects/arrays without resorting to the inefficiencies of deep equality checks, which in turn allows React to avoid expensive re-render operations when they are not required.

Should React lifecycle methods be implemented in container components or presentation components?

I'm attempting to implement container components in React and Redux, and I'm unsure of what should take responsibility for lifecycle methods; containers or presentational components. One could argue that the lifecycle methods are presentational as they control DOM updates, but in that respect, aren't they also behavioural?
Furthermore, all of the implementations of container components that I've seen thus far utilise the react-redux bindings, as do my own. Even if I keep the concerns clearly separated, is it appropriate to inherit from React.Component in the case of a behaviour component?
For example, the app on which I'm working has a Tab presentational component, with a shouldComponentUpdate method:
class Tabs extends Component {
shouldComponentUpdate(nextProps) {
const { activeTab } = this.props;
return activeTab !== nextProps.activeTab;
}
[...]
}
On the one hand, this seems like a presentational concern as it controls when component should re-render. On the other hand, however, this is a means of handling when the user clicks a new tab, updating the application's state via an action, thus I'd class this as behavioural.
Data should be controlled as close to the root of the tree as possible. Doing this provides some simple optimizations, being that you're only passing what you need.
This will bubble down to where you are controlling some lifecycle components. As mgmcdermott mentioned, a lot of lifecycle components really depend on what you're doing, but the best case scenario is to have the simplest, dumbest components.
In most of my projects, in my react directory, I have components/ and views/. It is always my preference that a view should do as much of the grunt work as possible. That being said, there a a number of components that I've built that use lifecycle methods like componentDidMount, componentWillMount, componentWillUnmount, but I typically try and isolate updates in my views, since one of their jobs, in my opinion, is controlling data flow. That means componentShouldUpdate would live there. Personally, I think componentShouldUpdate is purely end-of-the-line optimization, though, and I only use it in cases where I'm having large performance issues during a re-render.
I'm not super sure I understand your "inherit from React.Component" question. If you're asking whether or not to use pure functions, es6 class, or React.createClass, I don't know that there is a standard rule, but it is good to be consistent.
To address whether or not you are dealing with a behaviour or presentation, behaviour is the click, but re-drawing is presentation. Your behaviour might be well off to exist in your Tab component, where the re-draw in your Tabs view. Tabs view passes your method from redux to set the currently active tab into your individual Tab components, and can then send the behaviour of tab switching through redux so you can do your presentation componentShouldUpdate. Does that make sense?
So your mapToDispatch method in your container will have a function to set your active tab, let's call it activateTab(idx), which takes a 0-based index of the tab. Your container passes that to the containing component that you control, which is views/Tabs, and it passes that method along to components/Tab. components/Tab will have an onClick method which is listening on one of your DOM elements, which then calls this.props.activateTab(myIndex) (you could also pass a bound version of activateTab into components/Tab so it does not have to be aware of it's own index), which triggers redux, then passes back your data into views/Tabs which can handle a componentShouldUpdate based on the data from redux.
Expanded Edit: Since this was marked as accepted, I'll blow out my code example into something usable to the average person.
As a quick aside, I'm not going to write much redux, as this can be very app dependent, but I'm assuming that you have a state with activeTabIdx hanging off the parent.
containers/TabExample.jsx
import { connect } from 'react-redux'
import Tabs from 'views/Tabs.js'
const mapStateToProps = function (state) {
return {
activeTabIdx: state.activeTabIdx
// And whatever else you have...
}
}
const mapDispatchToProps = function (dispatch) {
return {
activateTab: function (idx) {
dispatch({
action: 'ACTIVATE_TAB_IDX',
idx: idx
}) // You probably want this in a separate actions/tabs.js file...
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Tabs)
views/Tabs.js
import React, { createClass } from 'react'
import Tab from 'components/Tab.js'
const { number, func } = React.PropTypes
// Alternatively, you can use es6 classes...
export default createClass({
propTypes: {
activeTabIdx: number.isRequired,
activateTab: func.isRequired
},
render () {
const { activeTabIdx } = this.props
const tabs = ['Tab 1', 'Tab 2', 'Tab 3']
return (
<div className='view__tabs'>
<ol className='tabs'>
{this.renderTabLinks(tabs, activeTabIdx)}
</ol>
</div>
)
},
renderTabLinks (tabs, activeTabIdx) {
return tabs.map((tab, idx) => {
return (
<Tab
onClick={this.props.activateTabIdx.bind(this, idx)}
isActive={idx === activeTabIdx}
>
{tab}
</Tab>
)
})
}
})
components/Tab.js
import React, { createClass } from 'react'
const { func, bool } = React.PropTypes
// Alternatively, you can use es6 classes...
export default createClass({
propTypes: {
children: node.isRequired,
onClick: func.isRequired,
isActive: bool.isRequired
},
handleClick (e) {
const { isActive, onClick } = this.props
e.preventDefault()
if (!isActive) {
onClick()
}
},
render () {
const { children, isActive } = this.props
const tabClass = isActive
? 'tabs__items tabs__items--active'
: 'tabs__items'
return (
<li className={tabClass}>
<a className='tabs__item-link' onClick={this.handleClick}>
{children}
</a>
</li>
)
}
That will mostly do the right thing. Keep in mind that this doesn't handle/care about tab content, and as a result, you may want to structure your view differently.
I think that this is a matter of opinion. I personally like to keep my presentational components as dumb as possible. This allows me to also write most of my presentational components as stateless functions, which are being optimized more and more in React updates. This means that if I can help it, I will prevent any presentational component from having an internal state.
In the case of your example, I don't believe that it is a presentational concern because componentShouldUpdate is a pure function of the props, which should be passed whenever this component is used. Even though this component updates the application's state, I believe that because it has no internal state, it is not necessarily behavioral.
Again, I don't think there is really a right or wrong way of doing things here. It reminds me of the discussion about whether or not Redux should handle all application state. I think if you keep the idea of making presentational components as dumb (reusable) as possible, you can figure out the correct place to put lifecycle methods in any case.
Your question is not very correct.
Simple act of using a lifecycle method doesn't define the component as a presentational or a container component.
Lifecycle methods are exactly that — the hooks for your convenience where you can do pretty much anything you want.
A container component typically does some setup that connects itself to your application's data flow in those lifecycle methods. That's what makes it a container component, not the bare fact that it uses some lifecycle methods.
Presentational components are typically dumb and stateless, therefore they typically don't need those lifecycle methods hooked into. This doesn't mean that it's always the case. A presentational component may be stateful (although this is often undesired) and a stateless component may make use of the lifecycle methods, but in a totally different fashion than a container component would. It might add some event listeners to the document or adjust the cursor position of an input in a totally stateless way.
And perhaps you're mixing up container components and stateful components. Those are different things, and while container components are stateful, stateful components don't necessarily acts as container components.

Resources