Stateless functional component vs. additional render method in a stateful component? - reactjs

As a really basic example, imagine I wanted to render a div containing some text outside of my render() method. Which of these options would be better?
class StatefulComponent extends Component {
...
render() {
return (
{this.renderTextDiv(this.state.text)}
)
}
renderTextDiv(text) {
return <div>text</div>
}
}
or
class StatefulComponent extends Component {
render() {
return (
<TextDiv text={this.state.text} />
)
}
}
function TextDiv({text}) {
return <div>{text}</div>;
}
Or would you completely pull the stateless component into its own class? Or does it just not matter at all? Does one make testing easier? Readability? Any differences at all?

It does not make any difference in terms of what is being displayed. However, it definitely changes the structure and readability of the code.
For myself, I try to divide the structure into as much Components as possible, and so does Thinking in react suggests. However, if you think that the element does not structurally differ from its parent component and thus does not deserve its own separate component but you require some readability and re-usability, the top code works.

The first one looks more concise in my opinion. You could render html in methods if it's not a big code, or, just a conditional rendering inside the component. Whenever you have some html rendering with a big structure and some functionality, it is always good to separate it into its proper component, because you probably would reuse this code later. Again: If it's not a big code or functionality, it's ok to use html rendering inside a method.

Related

static inside React component

Can anyone tell me what happens in line number 9 in the file Wizard.js here: https://final-form.org/docs/react-final-form/examples/wizard ? How does the unwrapping work and stuff like that?
I do understand the concept of children in React, I think, but not in this way. If I change the <Wizard.Page> inside index.js with <div> and remove the line 9 in Wizard.js, the code still work, but not if I just remove the line 9 in Wizard.js.
This line defines a very basic functional component, that simply renders its children.
It is defined as a static property on the Wizard class, so that it is accessible through Wizard.Page.
The code in Wizard.js does not really rely on the fact that the children of the Wizard component are actual Wizard.Page components - it just assumes that the children are the different steps in the wizard:
render() {
const { children } = this.props
const { page, values } = this.state
const activePage = React.Children.toArray(children)[page]
...
}
That's why it still works when you used <div> instead of <Wizard.Page>: the div elements act as wrappers around their children too, and the code in the render() method will still work as intended.
But the <Wizard.Page> approach has several benefits:
It makes the code in index.js more readable and explicit
If needed, the Wizard.Page component could evolve into a more complex component, with additional logic, without requiring any change in index.js

Best practice to catch last render in React Component

I have a question regarding a situation I am currently having. While I have found a workaround, I don't think it's the best practice. First thing my component does is make an API get call and send the results to the this.props. Following that I have a conditional check based on those props. Here's the problem, the component renders multiple times (4), and the prop being called is a prop from a previous state. So I have to wait for the second render before continuing. Here is a layout of my workaround.
import React from 'react'
class TestComponent extends React.Component{
componentDidMount(){
api = this.make.apiCall()
}
render(){
let something = null
console.log('Render Test Comp')
if(this.props){
something = (
<div>this.props Exsists</div>
)
}
return(
<React.Fragment>
{something}
</React.Fragment>
)
}
}
export default TestComponent
So basically what I want to know is, was the best possible method to catch the LAST render of a page? Is my method above ok? Is there a better way? Should I throw the conditional statement inline the JSX(which I think is so ugly and confusing if you have nested conditional statements inside your JSX)? You guys all rock, and have always answered my questions that are much more specific. This one should be easy ;)
I cannot answer your question here, because the code is wrong in many ways. Plus your code snippet does not make sense with the explanation.
Problem 1:
api = this.make.apiCall()
Where is this.make.apiCal()? What response is expected?
api should be a state from what I see. In order to rerender your component because of change got from api call.
Problem 2:
if(this.props){
something = (
<div>this.props Exsists</div>
)
}
This is absolutely wrong because this case will always be triggered. this.props is {} i.e. empty object which is truthy value.
See the Pen
Hello World in React by Tulsi Sapkota (#tolsee)
on CodePen.

React Native - Is extending a class acceptable in this scenario?

So, I have read multiple times: Composition is Good. Extending is Evil.
Now, I do use composition, basically a lot of stateless components and higher order components, however I do have one particular case where I extend a class.
Instead of every stateless component extending from Component, I am extending from my own BaseComponent, which basically has some helper functions that I use in all of my components.
Like for example:
Analytics helpers
Loggers
Data Fetchers
Configuration
Storage
Theme management
Actions
So far, I am happy with the result. I am looking for any good reason for me to actually break this pattern in the objective to pursuit great code.
Please no "React recommends composition" answers.
Well why not simply use HOC's for each of those pieces?
The big benefit of using HOC's for these kind of situations, is that you can apply them individually, or as a group. You gain a ton of control in how you slice/dice these shared pieces of functionality.
As a simple, example, your logger as an HOC might look something like;
const function loggerHoc(WrappedComponent) {
return class extends Component {
log(message) {
console.log(message); //or other implementation
}
render() {
<WrappedComponent log={this.log} {...this.props}/>;
}
}
}
Now if you had a second HOC of this style for analytics, they can be wrapped on top of one another without issue;
ResultComponent = loggerHoc(analyticsHoc(ChildComponent));
Which you could also write a function to do all of;
const function wrapWithAll(WrappedComponent) {
return loggerHoc(
analyticsHoc(
WrappedComponent
)
);
}
Or you can use individually, as your needs dictate.

How to re-use a method from one component to the next

I have a component that has grown rather large. I decided to break it up into two components, but have found that the component I have split off needs to utilize a method from the original component.
What is the best way to consume a method from inside of an existing component?
Thanks in advance!
Once upon a time, one would have used mixins to achieve what you are looking to do. Since then, this article came out : https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html
They are still an option in my opinion but require discipline so that you don't overuse the concept.
Other options for you would be:
a) Bring the desired method up one level. By that I mean you could declare it in the container component and pass it along a props to the 2 childrens.
b) If the method is generic enough, declare it in an utility class that you would import in both components. (using static is an option as well)
c) any other innovative way ;) (just to say that these are not the only options)
Extend your base class with in a Split off version. If you use ES6 it would look something like this:
class Base extends React.Component {
renderText () { return 'Hello'}
render(){
return <span>{this.renderText()}</span>
}
}
class SplitOff extends Base {
render() {
return <span>{`${this.renderText()} World`}</span>
}
}
JSFiddle of the above

How will React 0.14's Stateless Components offer performance improvements without shouldComponentUpdate?

This question has been going round and round in my head since I read the release notes (and other related hype) around React 0.14 - I'm a big fan of React and I think that stateless components (https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components) are an excellent idea, both for the ease of writing such components and for expressing in code the intention that these components should be "pure" in terms of rendering consistently for the same props data.
The question is: how will it be possible for React to optimise these stateless component functions without going whole-hog and assuming that props references are not only immutable in that they shouldn't be manipulated within the component, but also that they can never change outside of the component lifecycle? The reason that "regular" components (aka stateful components - in other words, the components that go through the whole lifecycle; componentWillMount, getInitialState, etc..) have an optional "shouldComponentUpdate" function is that React does not assume that all props and state references are completely immutable. After components have been rendered, certain properties of the props references may change and so the same "props" instance may have different contents later on. This is partially why there was a lot of excitement over the use of fully-immutable structures and why it was said that using Om with React could offer great performance gains; because the immutable structures used there guaranteed that any given instance of any object could never be mutated, so shouldComponentUpdate could perform really cheap reference equality checks on props and state (http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/).
I've been trying to find out more information about this but haven't got anywhere. I can't envisage what performance improvements could be made around stateless components without presuming that props data will consist of immutable types.. maybe some preliminary analysis of non-immutable props types to try to guess whether "props" and "nextProps" represent the same data?
I just wondered if anyone had any inside information or some otherwise enlightening insights onto this. If React did start demanding that props types be "fully immutable" (allow reference equality comparisons to confirm that data has not changed) then I think that would be a great step forward, but it could also be a big change.
Since your component is just a pure function of its parameters, it would be straightforward to cache it. This is because of the well known property of pure functions, for same input they will always return same output. Since they only depend on their parameters alone, not some internal or external state. Unless you explicitly referred some external variables within that function that might be interpreted as a state change.
However, caching would not be possible if your function component reads some external variables to compose the return value, so that, those external variables might change over time, making cached value obsolete. This would be a violation of being a pure function anyways and they wont be pure anymore.
On React v0.14 Release Candidate page, Ben Alpert states:
This pattern is designed to encourage the creation of these simple components that should comprise large portions of your apps. In the future, we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations.
I am pretty sure that he meant cacheability of pure functional components.
Here is a very straight forward cache implementation for demonstration purposes:
let componentA = (props) => {
return <p>{ props.text }</p>;
}
let cache = {};
let cachedA = (props) => {
let key = JSON.stringify(props); // a fast hash function can be used as well
if( key in cache ) {
return cache[key];
}else {
cache[key] = componentA(props);
return cache[key];
}
}
And there are other good properties of pure functional components that I can think of at the moment:
unit test friendly
more lightweight than class based components
highly reusable since they are just functions
Avoiding Unnecessary Allocations
If I understand correctly, stateless functional components are converted into regular components. From the source:
function StatelessComponent(Component) {
}
StatelessComponent.prototype.render = function() {
var Component = ReactInstanceMap.get(this)._currentElement.type;
return Component(this.props, this.context, this.updater);
};
When an instance of a stateless component is created, a new object is allocated. This new object has lifecycle methods such as componentWillMount and componentWillReceiveProps. I'm guessing that the plan is to not create these objects at all. Not creating the objects will avoid unnecessary allocations.
Avoiding Unnecessary Checks
Implementing the lifecycle methods requires a number of checks like this:
if (inst.componentWillUpdate) {
inst.componentWillUpdate(nextProps, nextState, nextContext);
}
Stateless functional components can be assumed to not have these lifecycle methods. That could be what the docs are referring to, but I'm not sure.
EDIT
Removed stuff on memoization, which didn't answer the question or explain stuff well.
You can use a decorator to compose your stateless function components to perform high order optimisation to determine if React should renders this component or not. I'm using immutable to perform strict equality checks between props.
Let's say we have this kind of component :
ClickableGreeter.js
const ClickableGreeter = (props) => (
<div onClick={(e) => props.onClick(e)}>
{"Hello " + props.name}
</div>
)
ClickableGreeter.propTypes = {
onClick: React.PropTypes.func.isRequired,
name: React.PropTypes.text.isRequired
}
export default ClickableGreeter;
We want React to not rendering it if the name does not change. I'm using a simple decorator that use immutable library to create immutable representation of props and nextProps and perform a simple equality check :
pureImmutableRenderDecorator.js:
import React from 'react'
import Immutable from 'immutable';
const pureComponent = (Component, propsToRemove = []) => {
class PureComponent extends React.Component {
constructor(props) {
super(props);
this.displayName = 'PureComponent';
}
comparator(props, nextProps, state, nextState) {
return (
!Immutable.is(Immutable.fromJS(props), Immutable.fromJS(nextProps)) ||
!Immutable.is(Immutable.fromJS(state), Immutable.fromJS(nextState))
)
}
removeKeysFromObject(obj, keys) {
var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target;
}
shouldComponentUpdate(nextProps, nextState) {
let propsToCompare = this.removeKeysFromObject(this.props, propsToRemove),
nextPropsToCompare = this.removeKeysFromObject(nextProps, propsToRemove);
return this.comparator(propsToCompare, nextPropsToCompare, this.state, nextState)
}
render() {
return <Component {...this.props} {...this.state} />
}
}
return PureComponent;
}
export default pureComponent;
Then, you can create a PureClickableGreeter component by doing :
const PureClickableGreeter = pureComponent(ClickableGreeter, ['onClick'])
//we do not want the 'onClick' props to be compared since it's a callback
Of course, using immutable here is overkill because it's a simple string comparison but as soon as you need some nested props, immutable is the way to go. You should also keep in mind that Immutable.fromJS() is a heavy operation, but it's fine if you do not have to many props (and that's normally the whole point of stateless functional components : to keep as many props as possible for better code splitting and reusability).
There's finally an answer! I'm not sure what version of React that this arrived in (I suspect that 0.14 did not include this but merely laid the groundwork) but now a PureComponent does not implement "shouldComponentUpdate" because it is handled automatically by React, which:
only shallowly compares the objects
This does mean that you have to be careful about using this type of component if you can't reliably detect changes with a shallow comparison but, if you can, it makes them very performant and can potentially avoid a lot of changes to the virtual DOM!
See here for more info ReactJs.org's 'React.PureComponent' section.

Resources