React Best Practices: Where to *not* render a component? - reactjs

I came across some code in review and had a question on best practices. Here's the scenario:
I've got a Hyperlink component with a url prop. If for some reason url is falsy, Hyperlink renders null.
simplified example:
const Hyperlink = ({ url }) => {
return !url ? null : <SomethingElse url={url} />;
};
Does this logic belong in the Hyperlink component, or should it be the responsibility of the parent component to determine whether or not to render something?
example:
const MyParentComponent = ({ url }) => {
return !url ? null : <Hyperlink url={url} />
};
This keeps Hyperlink dumb, with the downside of having to sprinkle that logic in places url is optional.

I would say, as a generic rule, there is "avoid surprises", or "reduce WTFs per minute", or "explicit is better than implicit". Getting null instead of a <Link /> is well sort of a "surprise".
I think it may be somewhat similar to "pointers vs references", when a pointer can have a null value, whereas a reference can't. References are safer, because you don't need to worry about the null value. Consider passing that <Link /> component to some callback or argument. For example, SomeComponent here may be shocked by getting null:
const content = <Link>;
<SomeComponent contents={content}>
But in principle I think both approaches are fine.

If the conditional rendering is :
condition ? something : null
I prefere using:
condition && something
Since conditional rendering should be used for cases like:
condition ? something : somethingElse
Back to your question, if the Component has some heavy calculations before the return, it's common sense that you are wasting resources performing them since it won't return nothing if condition is false, so it' s better to use:
condition && <Component/>
But in most cases, especially if you have stateless components with no logic like that one, you won't experience particular differences between the two approaches, basically by doing the conditional rendering inside the component, you are just wasting a React.createElement().
I personally use
condition && <Component/>
in cases like that, if it's possible, since I find to be very semantically uncorrect for a Component to possibly render nothing. If you call your Component HyperLink, I expect it to return something, possibly a link. There are cases where you are forced to return nothing, and it's okay, but I try to avoid it.

Usually these type of checking should be done using Typescript.
Answering to your question it should depend upon your project scenario.
If you feel the url the Hyperlink component will receive can be null or undefined you can put the check in the Hyperlink component.
But if you think only in MyParentComponent the case will occur where url will be null you can think of conditionally rendering the component.

Related

is <this.props.Component /> a correct syntax in React JSX?

I have a strange case where I used code splitting within React SPA.
My code needs to render sometimes thin component, and in other cases a full component (for logged-in users).
now, Component has been sent to the class as part of props, and within render function I'm trying to render:
<this.props.Component />
and, here is the strange case. sometimes this line of code throws error:
error Cannot read property 'Component' of undefined
with stack trace that pointing to this line. In other cases it works perfectly.
Could anyone explain if this syntax is wrong? or maybe what causes it not to work sometimes?
Seems that the correct answer is that this syntax is not allowed (as of React 16),
I still can't understand why it had worked for me,
but if someone needs to render a component based on props he gets, he has to do it this way (thanks to #David):
{this.props && this.props.Component({
onClickHandler: this.onClick,
currentUser: this.props.currentUser,
etc..
})}
and type of Component must be a function.
another option to whom may want to write pure JSX:
const { Component } = this.props
return (
<Component
currentUser={this.props.currentUser}
onClickHandler={this.onClick />
)

Are there any benefits of calling an SFC function within the render method?

I am working with the react-gsap library, and want to encapsulate specific <Tween> instances that do not need any props, because they are occuring multiple times in the same way.
Lets take a simple example of an instance, that doesn't need any props or state at all. Let's say this line
<Tween
to={{opacity: 0}}
duration={5}
/>
occurs really often in our code base, and we want to abstract it.
My first idea was to just create an SFC for that:
const HideTween = () => (
<Tween to={{ opacity: 0 }} duration={5} />
);
// and then ...
<HideTween />
but that seems not to work at all. The Tweens are simply not showing any effect.
I then came up with another idea (which i personally dislike) to just call the SFC. Instead of <HideTween /> , we now have
{HideTween()}
and voila, it works...
I am specifically curious now, why my first idea did not work at all. The question is not aimed into the gsap library directly, but more of a general form: Where, when and how can such an approach (of abstracting parts of your render into own functions) fail? If it is the library, how does it even achieve such a behaviour?
And why does it seem to work, when i call the function directly (i know this is kind of a bad approach)? Without any state or props present,
shouldn't <HideTween /> have the same effect on every render as {HideTween()}?
EDIT
Here is a minimal example
Exchange <Tweens /> in line 38 with the content of the Tweens SFC, and you will see the animation again.
You can share the same elements between different render methods by creating them ahead of the render cycle as you tried to do:
const HideTween = <Tween to={{ opacity: 0 }} duration={5} />
and then directly using the element (not instance) in the render methods:
<Timeline>
{HideTween}
</Timeline>
<Component /> is JSX sugar for creating an element of a react component. So your first idea didn't work as it would return an element returning an element of a Tween and not directly the Tween element. For usual DOM rendering this will work as expected, though. The second example works as you get the Tween element this way, but you're right to dislike it as it simply adds an unnecessary indirection.
Doing it this way you might think that react will reuse the same instance of the component in different places, but it will actually instantiate the component anew for each usage. Here is an example:
https://stackblitz.com/edit/react-rzq5q5?file=index.js
I assume this is intentional as sharing the same instance of a component seems to be quite a rare use case and with stateful components the state would be shared as well synchronising components in different parts of the app (which could end up being quite confusing).
Also check out this article on the difference between components, elements and instances (instances will be created by react for you): React Components, Elements, and Instances
Here I've set up a simple example trying out a few things: Example
In your Tween component:
class Tween extends React.Component {
static defaultProps = {
to: {opacity: 0},
duration: 5
}
...
}

Update Events in React : order?

Suppose I have something like this where both components A and D listen to changes in a global store :
import React from 'react'
import useStore from 'whatever-global-store-manager'
function A() {
const [store] = useStore()
if(!store.currentUser)
return <h1>You must log in</h1>
else return <B/>
}
function B() {
return <C/>
}
function C() {
return <D/>
}
function D() {
const [store] = useStore()
console.log(store.currentUser) // Can it be falsey ?
return <h1>{store.currentUser.name}</h1>
}
In A, when currentUser is falsey, B is not rendered, thus D is not rendered. But suppose this scenario :
At first, currentUser is defined as an object with a name property, so D renders, listens to changes in the store and renders the name.
Then, somewhere else in the app, currentUser is set to null.
In which order are the "listeners" processed ? Is there any chance that function D is executed with currentUser to null even when begin ultimately removed from the component tree ?
Another way to formulate the question : Should I check against currentUser in component D before accessing its name property ?
I was looking in the doc for a rule like "When two components listen to the same event, the one higher in the hierarchy is rendered first, and if it turns out the second one should be unmounted according the first's output, then the second one is never even called", but couldn't find anything. In practice, I know it works, but I would like to be sure that it's not just luck.
I believe this largely depends on the store observer mechanism, so it's hard to give a conclusive answer without knowing which store you're using. If observers are registered in order, that might affect how you need to deal with it.
If you wanna find out for sure, you could console.log your render methods, or use debugger while changing the value of currentUser.
Analysis of a hypotetical implementation: let's say an observer is registered when the component mounts, and unregistered when it unmounts. In this situation, the component A would trigger first (since it was registered first), and cause D to unmount, unregistering his trigger. In this hypothetical scenario, D wouldn't need to check for null.
Unrequested advice: a good thing for you might be centralizing the "data collection" in one parent component, while the children just receive that as props and render (without observing the store). I've found (both from lore and personal experience) that it simplifies a lot the development process.
Another way to formulate the question :
Should I check against currentUser in component D before accessing its name property ?
Yes, it is definitely a good decision: it is preferable that there is one redundant code line, instead of obtaining an error.
I was looking in the doc for a rule like
"When two components listen to the same event,
the one higher in the hierarchy is rendered first...
I think the opposite. Although I neither could find the specific documentation to explaine it, I remember that Components do not update like a cascade. That is the idea of the component oriented programming: each one is an independent entity.
Note: if I understand your example well, you could test this example by adding a setTimeout that wraps the return of function A, right? So this way you can then set currentUser as null and D wil be still rendered and you can see what happens.

Passing more parameters to a pure render function in React

Lately I've been trying to write my React components as "Pure Functions" and I've noticed that sometimes I want to have something which feels a lot like state. I was thinking about passing my state as a second parameter to my component. I can achieve this by calling my component as a normal function with two parameters, props and state.
For example:
// abstracted to it's own module
const useState = (Component, state = {}) => {
return class extends React.Component {
state = createState(this, state); // will traverse and update the state
render() {
const { props, state } = this;
return Component(props, state); // <-- call the Component directly
}
};
};
const Component = (props, { index, increase }) => (
<div onClick={increase} {...props}>
Click me to increase: {index}
</div>
);
const componentState = {
index: 0,
increase: (event, state) => ({ ...state, index: state.index + 1 })
};
const StatefullComponent = useState(Component, componentState);
<StatefullComponent style={{ color: "purple" }} />;
I have a CodeSandbox example:
My questions are:
Will this pattern harm performance?
I'm no longer extending the props with state values, this might be a good thing
I am messing with the way components are rendered by default, this might be a bad thing
Will this Pattern break things like shouldComponentUpdate? (I have a sinking feeling this is modelling the old context api)
How worried should I be that future react updates will break this code?
Is there a more "Reacty" way of using State in a Pure function without resorting to libraries like Redux?
Am I trying to solve something which should not be solved?
Note: I'm using state in this example, but it could also be a theme, authorisation rules or other things you might want passed into your component.
EDIT 19-03-2018: I have noticed that people seem to be confused about what I'm asking. I'm not looking for a new framework or a conversation about "why do you want to separate your concerns?". I am quite sure this pattern will clean up my code and make it more testable and "cleaner" in general. I really want to know if the React framework will in any way hinder this pattern.
At first glanced when I checked your code I had a question:
"Why do you make it so complicated? When you can simply make it with a class declaration".
But later when I have splitted your code I found it really worth to do that.
Question 1: Doesn't really make a difference, it is the way how HOC does the composition.
I'm no longer extending the props with state values, this might be a good thing
Why/When might it be a good thing?
I am messing with the way components are rendered by default, this might be a bad thing
I don't see that you break or mess the rendering by default, I think the HOC pattern promotes the same philosophy, the difference you separate state from props.
Question 2: If a developer decide to use a stateless component then he/she should realize all “lifecycle methods” or references ref will be not available.
Your pattern make stateless component as “statefull” but in stateless declaration - amazing 😋.
Like in JSX you write in JS an "HTML" and inside it JS code with another "HTML":
<ul>
{list.map(text => <li>text</li>)} // I know there should be used key
</ul>
Mr. Baudin pattern (state-full like stateless):
import React from 'react'
import {useState} from './lib'
const state = {
index: 0,
increase: (event, state) => ({index: state.index + 1})
}
const Component = (props, state) => (
<div onClick={state.increase} {...props}>
Click me to increase: {state.index}
</div>
)
export default useState(Component, state)
Question 3: It depends what break changes will be in coming versions.
Question 4: Well... I don't think the offered pattern (implemented library) can be considered as application state management but it can be used within any state management like Redux or Mobx because it deals with internal component state.
Question 5: No, I don't think. Your solution makes code less and clean. Functional components are good for very simple or representational components and now it can be extended with state.
While this question has been open I've done some painful research on the subject and I'd like to share this research with you.
Question 1: Performance; Calling your components as functions or even as constructor functions doesn't really make a difference. You simply get your component instead of a type.
// the component
const MyComponent = () => (<div>This is my page</div>);
console.log(MyComponent());
console.log(new MyComponent());
console.log(<MyComponent />);
console.log(React.createElement(MyComponent));
Pen (Don't forget to inspect the developer tools!)
What I've noticed is that when you call a component directly you lose a little information, for example, when I use JSX the type information is preserved:
React.createElement(MyComponent).type === MyComponent // <- true
MyComponent() // <- Now way to find out what constructed this...
This doesn't seem like a big deal because the MyComponent() is seen as a normal div so it should render correctly; but I can imagine that React might do some lookup on the type of the component and calling your function like this that might interfere with the performance.
Haven't found anything in the documentation nor in the source code to suggest that this is the case, so I see no reason to worry about performance at this point.
Question 2: Does this break shouldComponentUpdate; the answer is "maybe not", but not because I need to write a class as was suggested. The problem is that React does a shallow compare on the props when you use a PureComponent and with pure functions just expects that with the same props you get the same result. In my case, because of the second parameter it might think the component doesn't need to update but actually it should. Because of some magic in my implementation this seems to work for child components of a root component wrapped with the useState function.
This is as I expected the same problem as with the original implementation of the context api. And as such I should be able to solve it using some reactive techniques.
Question 3: Seeing how "just calling a component as a function" seems to be the entire idea behind react and seeing how it results in almost exactly the same component without the original type information I see no reason why this should break in the future.
Question 4/5: No, there is no more "Reacty" way of really solving this problem. There is how ever a more functional way. I could use a state monad and lift the entire thing up; but that would envolve a lot of work and I really can't see the benefit of doing that. Passing state as a second parameter seems, at least for now, as something which might be strange but viable and actually feasable.
Question 5: When I started looking around I didn't find a lot os answers to these questions, but now that I've really dug myself in I can see a few other libraries doing the same thing. For example: recompose which calls itself "lodash for react". They seem to use this pattern of wrapping your component in a function and returning a class a lot. (Their withState implementation).
Extra information: My conclusion is that this pattern (because it's nothing more than a pattern) is valid and does not break any fundamental rules of React. Just to give a little bit of extra information Bernardo Ferreira Bastos Braga wrote that I needed to use a class to do it "the React way". I fail to see how wrapping your function and returning a class with state is anything other than "using a class".
I do however realise that wrapping a function increases complexity, but not by much; function calls are really optimised and because you write for maintainability and optimise later.
One of my biggest fears is that when the software gets more and more complocated and we get more cross-cutting concerns to deal with, it will get harder and harder to handle every concern as a parameter. In this case it might be good to use a destructuring pattern to get the concerns which you need from a "concerns" obejct passed as the second parameter.
One last thing about this pattern. I've done a small test (Just selenium rendering a page a 100 times) and this pattern, on a small scale, is faster than using Redux. The bigger your redux state gets and the more components you connect the faster this pattern becomes. The down side is that you are now doing a bit of manual state management, this comes with a real cost in complexity. Just remember to weigh all options.
A few examples of why this state component
Applications which interact with users, require that you try to keep track of the interactions they have. These interactions can be modeled in different ways but I really like a stateful approach. This means that you 'thread' state through your application. Now in react you have a few ways of creating components. The three I want o mention are:
create a class and extend from Component
create a class and extend from PureComponent
create a stateless function
I really like the last option but, to be honest, it's a pain keeping your code performant. There are a lot of articles our there explaining how lambda expression will create a new function every time your component is called, breaking the shallow compare of the props done by PureComponent.
To counteract this I use a pattern where I wrap my stateless component in a HoC where I pass my component and my state object. This HoC does some magic and passes the state as a second parameter to the stateless function, ensuring that when the props are tested by the compare of the PureComponent it should work.
Now to make the wrapper even better I memoize the lambdas so that only a single reference to that function exists so that even if you were to test the function by reference it should still be OK.
The code I use for this is:
return Object.entries(_state).reduce(
(acc, entry) => {
const [key, value] = entry;
if (value instanceof Function) {
acc[key] = _.memoize(item => (...args) => {
const newState = value.apply(null, [...args, root.state, root.props]);
root.setState(newState);
});
} else {
acc[key] = value;
}
return acc;
},
{}
);
};
As you can see I memoize the function and call it proxying the arguments and passing in the state and the props. This works as long as you can call these functions with a unique object like so:
const MyComponent = useState((props, { items, setTitle }) => {
return (
<div>
{items.map(item => (
<Component key={item.id} item={item} changeItem={setTitle(item)} />
))}
</div>
);
}, state);
1- Will this pattern harm performance?
Performance is usually not a black/white, rather it is better / worse in different scenarios. Since React already has a standard way of doing this, it it plausible that you'll be missing out on internal optimizations.
2-Will this Pattern break things like shouldComponentUpdate? (I have a sinking feeling this is modelling the old context api)
Yes, you should be using the class declaration if you need to write shouldComponentUpdate functions
3- How worried should I be that future react updates will break this code?
I think is fair to say that you should, since there are obvious and documented ways of doing the same using classes.
4 - Is there a more "Reacty" way of using State in a Pure function without resorting to libraries like Redux?
you could have a container component that has state and pass down callback functions to update the state
5- Am I trying to solve something which should not be solved?
yes, since there is already a mainstream and documented way of archieving what you need using the Component class. You should probably resort to functional components only for very simple or presentational components

React component mounting/unmounting with regard to if else statement in render

When exactly is a child component constructed vs rerenderes? I googled that the key property might have something to do, but I can't figure it out. Also, say in the parent render function I have if true return A, else return B. What happen in this situation?
If A and B are different components, React will unmount one and mount the other if something has changed.
But, if they are the same, the reconciliation algorithm might just change any refs, change the props and call update. I agree that the docs are not clear enough there and I'm unsure if and when have any changes been made from version to version.
However, if this is the case (A and B are from the same component) you should not be writing your code like that but rather something like this:
<Component { condition ? ...propsA : ...propsB } />

Resources