When clicking the button, you will see n is getting bigger but the UI remains 1
<script>
let n = 1
function add() {
console.log(n)
return ++n
}
export default {
functional: true,
render(h, ctx) {
return (<div>
<h1>{n}</h1>
<button onClick={add}>click</button>
</div>)
}
}
</script>
Intended Behavior
This is the intended behavior of functional components and the thing that makes them functional. From the docs:
...we can mark components as functional, which means that they’re stateless (no reactive data)
Since functional components are just functions, they’re much cheaper to render.
Explanation
What this means-- and the reason n is not reactive-- is that n is not observable and has no dependency management/watching. This lack of dependency overhead is also the reason for the performance increase of functional components. You get speed at the cost of observability, which is a nice tradeoff if you don't need it. If you do, there would be no reason to use a functional component.
How to proceed
So, you could proceed to simply use a non-functional component, or, reason about whether it's possible to subdivide your functional component further and encapsulate only the reactive portions into a non-functional subcomponent.
Other thoughts
If you manually added observability to your functional component, you would get the behavior you wanted, though there's no reason to do this over using a non-functional component. Notice the use of observable:
import Vue from 'vue';
let state = Vue.observable({n: 1});
function add() {
console.log(state.n)
return ++state.n
}
export default {
functional: true,
render(h, ctx) {
return (<div>
<h1>{state.n}</h1>
<button onClick={add}>click</button>
</div>)
}
}
(Note: You can use render functions in normal components as well. I say this just in case you had a misunderstanding that a functional component was required for render functions.)
Related
For rendering smaller components/jsx within a bigger component, there are multiple approaches that one can follow. For example, consider this:
Method 1:
function BigComponent(props) {
const renderSmallComponent1 = () => <div>{props.a}</div>;
const renderSmallComponent2 = () => <div>{props.b}</div>;
return (
<div>
{renderSmallComponent1()}
{renderSmallComponent2()}
</div>
)
}
Method 2:
function BigComponent(props) {
const smallComponent1 = <div>{props.a}</div>;
const smallComponent2 = <div>{props.b}</div>;
return (
<div>
{smallComponent1}
{smallComponent2}
</div>
)
}
Method 3:
function SmallComponent1({ a }) {
return <div>{a}</div>;
}
function SmallComponent2({ b }) {
return <div>{b}</div>;
}
function BigComponent(props) {
return (
<div>
<SmallComponent1 a={props.a} />
<SmallComponent2 b={props.b} />
</div>
)
}
I am just trying to understand the difference in these 3 in terms of
dev experience,
how the framework treats them,
are there any performance optimizations,
are there differences in runtime behaviours in all of these?
Is either one better to use in certain scenarios?
These are the things that I understand:
in Method 3, all SmallComponent are React components which are rendered in another component, so they would have a component lifecycle, while in method 1 and 2, they are simple jsx, which does not have lifecycle, so they would not be mounted / unmounted as React components
in Method 2, we would be eagerly evaluating the JSX as it is directly a variable, while in method 1, it would only be evaluated when the function is called in render. So, in case, we have any conditional rendering, the eager evaluation might just be wasteful.
A few other helpful articles:
https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f
https://kentcdodds.com/blog/dont-call-a-react-function-component
UPDATE: it seems observation 1 is incorrect as all 3 of them would still be rendered as react components, and hence would have a component lifecycle. So react would mount/unmount them.
UPDATE 2: No, observation 1 is correct, method 1 and 2 are both treated as regular jsx as part of the BigComponent and they are not treated as react component which have a lifecycle.
UPDATE 3:
There is another method Method 4:
function BigComponent(props) {
const SmallComponent1 = () => {
return <div>{props.a}</div>;
}
const SmallComponent2 = () => {
return <div>{props.b}</div>;
}
return (
<div>
<SmallComponent1 />
<SmallComponent2 />
</div>
)
}
this is similar to Method 3, but Method 3 vs Method 4 is slightly different in execution, when debugging through dev tools.
Method 2:
function BigComponent(props) {
const smallComponent1 = <div>{props.a}</div>;
const smallComponent2 = <div>{props.b}</div>;
return (
<div>
{smallComponent1}
{smallComponent2}
</div>
)
}
If you want to a large UI into seperate smaller UI, this method will give you best performance because
It is still just one big UI component.
react just have to solve variable references.
while re-rendering, BigComponent,smallComponent1 and smallComponent2 are rendered together as single unit.
smallComponent1 and smallComponent2 cannot have their own state, life cycles and hooks.
smallComponent1 and 2 needs to be re-initialized everytime Bigcomponent state is changed. So it is good practise to wrap them with useMemo() if the result of those smallComponents are coming from an expensive computation.
Method 3:
function SmallComponent1({ a }) {
return <div>{a}</div>;
}
function SmallComponent2({ b }) {
return <div>{b}</div>;
}
function BigComponent(props) {
return (
<div>
<SmallComponent1 a={props.a} />
<SmallComponent2 b={props.b} />
</div>
)
}
React needs to resolve reference as well as execute the function after resolving the reference.
It is a composition of react's actual child components into a large Component.
Child components are allowed to have their own hooks.
Child components are not re-initialized but are re-rendered if BigComponent state is changed.
There is chance of SmallComponent1 and SmallComponent2 getting re-rendered multiple times on BigComponents rendering once if small components are updating thier own state based on props change in parents.
if each SmallComponents are supposed to use multiple props which state of BigComponents, Keeping SmallComponents outside BigComponent does offer good developer experience.
I hope Method 1 and Method 4 can also be understood using these above points.
Note: childcomponents stored in variable and childcompoents as function becomes tricker if your application logic is using ref or DOM element for maininting focus or anchor point of rendering.
Have you taken a look at the compiled JS in a React project?
JSX tags are essentially transformed in to React.createElement statements. You can read the docs here. Essentially the syntax is:
React.createElement(FunctionOrClassComponent, { props }, ...children)
In all three of your examples this would take place. In all three examples, the smaller components are functional components rather than class components. That is to say, they don't have the React lifecycle methods of a class component, but they can use equivalent React hooks - should you want to.
Edited: Evaluation (instantiation and rendering) depends on your render logic. If you have conditional rendering statements or your functions return null (or less content) based on certain conditions, then obviously you're doing less work. And as you rightly pointed out in the comments below, when you assign a JSX.Element to a variable, that is evaluated inline rather than as a result of a function - so that happens immediately.
To me, all three are valid approaches. To address your questions:
dev experience,
for small components with minimal state, functional components as variables or lambdas are convenient to write and easily read/parsed when revisiting code at a later date. When a component becomes more complex, you may have to reconsider how it's written and perhaps use Class components.
how the framework treats them,
to my knowledge the framework treats all three of your examples the same in terms of compilation. I'm unsure about rendering optimisation.
are there any performance optimizations,
your examples don't depict anything computationally onerous so performance optimization options are not so obvious
are there differences in runtime behaviours in all of these?
they are all translated to React elements, monitored for props changes, and re-rendered if parents re-render (if things like React.memo are not employed) -- there may be differences vs class-based elements, but I would guess that the runtime differences between your three examples are minimal
Is either one better to use in certain scenarios?
The differences between all three are more a matter of standards or etiquette than functional outcome. As a developer, I would be able to read and understand all three, but working in a team - I would want to see a standard approach.
I am learning ReactJS and I've learned that there are UI Components and Container Components. The Container Components are implemented using classes extending React.Component and contain state and good old render method, whereas the UI Components are created using functions and they are concerned with UI only as they only take the data from props.
Sample stateless functional components:
const Ninjas = (props) => {
const { ninjas } = props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
};
export default Ninjas;
The same sample as a Container Component
export default class Ninjas extends Component {
getRandomColor = () => {
....
return color;
};
render() {
const { ninjas } = this.props;
const ninjalist = ninjas.map((x) => {
var divStyle = {
color: this.getRandomColor(),
};
return (
<div className="ninja" key={x.key} style={divStyle}>
<p>Name: {x.name}</p>
<p>Age: {x.age}</p>
<p>Belt: {x.belt}</p>
</div>
);
});
return <div className="ninja-list">{ninjalist}</div>;
}
}
So my question is why do we even bother to make a UI component (not using the render method which is used in Container Component) when we could have easily done the same thing as a Container Component.
Functional state-less components (what wrongly you refer as UI Components, all components are UI components both statefull and stateless) are simply a short-hand method to create components that simply render something based on props passed and do not need to keep internal state.
Of course one can always use class-based components which extend React.Component. But why not have a short-hand to save time and space and simplify things if we can. There is nothing forcing you to create functional components, you can always use class-based components, only if you need to simplify and save time and space.
According to Functional vs Class-Components in React article:
So why should I use functional components at all?
You might ask yourself why you should use functional components at
all, if they remove so many nice features. But there are some benefits
you get by using functional components in React:
Functional component are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks
You end up with less code
They help you to use best practices. It will get easier to separate container and presentational components because you need to think more
about your component’s state if you don’t have access to setState() in
your component
The React team mentioned that there may be a performance boost for functional component in future React versions
I would add a 5th point that React references (with React 16.3+) which provide functionality to access the DOM nodes directly cannot be used with Functional Components.
In React v.16.8+ useState hooks are introduced which enable functional components to be state-full while still being functional.
Furthermore with the introduction of React.memo higher-order component we can use memoization to avoid re-rendering of a functional component given that it renders same stuff for same props (shallow tested for difference)
We're trying to customise the arguments of a HOC (specifically react-graphql). Due to how this particular library HOC works, we have no ability to influence the component state (queries and options) after the HOC is called.
In a traditional HOC factory like connect() in Redux, all contained logic is applied immediately - which is too early for us. Instead, I'm deferring application of the original HOC (applyOriginalHOC()) until the construction of the first instance from this component.
export function applyLazyHOC(args) {
return function wrap(WrappedComponent) {
let ComponentWithLazyHOC; // Closed-over value is scoped to component
class LazyHOC extends Component {
constructor() {
super();
// Lazy initialising of HOC to give customisations an opportunity to be registered
if (!ComponentWithLazyHOC) {
ComponentWithLazyHOC = applyOriginalHOC(
// Adds customisations which have been registered by third party code
myCustomization(args)
)(WrappedComponent);
}
}
render() {
return <ComponentWithLazyHOC {...this.props} />;
}
}
return LazyHOC;
};
}
It seems like a slightly unconventional approach, so I'm looking for feedback:
Can you see any side effects of changing the initialisation order of HOCs? I'm assuming HOCs shouldn't rely on the presence of other HOCs.
Static analysis (e.g. in IDEs) isn't possible with HOCs anyway, so a lazy evaluation doesn't make this any better or worse, right?
HOCs can provide context to React components, which accumulates across nested components - the order shouldn't matter, right?
A component definition never gets unloaded, and ComponentWithLazyHOC is only created once per component (not component instance). Can you see any potential for memory leaks?
I have been creating a small app using react.js. I take 'performance' into account excessively.
So I have a simple child component named "Spinner". My goal is to make sure this component never re-renders.
Here is my component:
import React, {PureComponent} from 'react';
export default class Spinner extends PureComponent {
render() {
return (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
)
}
}
In the time of the re-rendering with 'react-addons-perf', the component is always rendering, I am using PureComponent because I want that component to render only one time, I read that I can use immutable props but I don't know how to make this possible.
If I make some like to this:
componentDidMount() {
this.renderState = false;
}
shouldComponentUpdate(nextProps, nextState) {
return (this.renderState === undefined) ? true : this.renderState;
}
It is rendering only one time, but I believe that there is a better way.
How do I avoid the re-render? or maybe How I can make a immutable props?
You don't need an extra logic for componentShouldUpdate, since you don't want your component to rerender ever.
Adding only this should be enough to prevent component to rerender:
shouldComponentUpdate(nextProps, nextState) {
return false
}
For stateless components that don't need props, we can use a combination of a Functional (stateless) component, and babel's React constant elements transformer to optimize the component creation, and prevent rerenders entirely.
Add React constant elements transformer to your build system. According to the docs the transformer will:
Hoists element creation to the top level for subtrees that are fully
static, which reduces call to React.createElement and the resulting
allocations. More importantly, it tells React that the subtree hasn’t
changed so React can completely skip it when reconciling.
Change the spinner to a stateless component.
const Spinner = () => (
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
);
export default Spinner;
You can make your props immutable in React by using Immutable JS to transform your array props into Lists and object props int Maps. With this library you can use simple checks to check the equality of arrays/objects (instead of going through keys/values for equality):
shouldComponentUpdate(nextProps) => {
this.props.complexObjectAsMap === nextProps.complexObjectAsMap
}
But since your component doesn't have any props - this doesn't look the right question. In your case I'd go with Ori Drori answer.
I'm trying to understand stateless components and what the difference is between these examples:
class App {
render() {
return (
<div>
{this.renderAFunction('hello')}
</div>
);
}
renderAFunction(text) {
return (
<p>{text}</p>
);
}
}
and this:
class App {
render() {
return(
<div>
<RenderAFunction text='hello'/>
</div>
);
}
}
const RenderAFunction = ({text}) => (
<p>{text}</p>
);
Or if there is any difference at all?
Functionally, there is absolutely no difference. Both end up rendering a paragraph element, but there are other aspects to consider. There are three points to make (in my opinion) when examining both methods:
Reusability: You have to understand to separate components when you need to. If renderAFunction is just meant to generate some JSX based on, for example, an API request, then it's fine being in a method. But if you want to reuse it somewhere else, then separate it into it's own component. A huge part of React is component reusability and getting rid of code duplication. Separating the method into it's own component would be imperative to accomplish this.
Purpose: There are reason to use stateless function components and reasons not to. The whole point of stateless functional components is to not have state and be presentational. If you need to do something that involves the React lifecycle or internal state, keep it as a method, or new class depending on if you want it reusable.
Performance: Using a stateless functional component would be less efficient. This is because it's a component, not just some JSX returned from a method. As of right now, the React team plans on making some optimizations for stateless functional components because they do not contain state and are merely presentational, but this probably won't happen until after React Fiber is done and thus your stateless functional component has no optimizations versus a regular full-fledged class component. That makes it incredibly inefficient versus a method returning some JSX, especially if it's just used once in another component.
A good rule of thumb is to ask yourself, do I need it anywhere else? If not, then keep it in a method. If you don't need it anywhere else, separating the JSX into a separate component would have worse performance and wouldn't follow React's core principles.
If you are going to need it somewhere else, then separate the component so you follow React's concept of reusability.
Your App's render function will be translated into following JS code for your first example:
render() {
return React.createElement(
'div',
null,
this.renderAFunction('hello')
);
}
And the following one for the second one:
render() {
return React.createElement(
'div',
null,
React.createElement(RenderAFunction, { text: 'hello' })
);
}
While they both looks almost the same, there is one significant difference: laziness. React will execute RenderAFunction body only in case it gonna be mounted to the DOM hierarchy.
It is insignificant is your case, but imaging following example:
const LazyApp = () => {
const heavy = <div><HeavyStuff /></div>
// ...
return <div>done it</div>
}
const HardWorkingApp = () => {
const heavy = <div>{HeavyStuff()}</div>
// ...
return <div>done it</div>
}
const HeavyStuff = () => {
// ... do heavy rendering here
}
Lazy app will not perform any heavy stuff at all. Maybe it is not very clear from that synthetic example why one would do anything like that at all. But there are real-world examples out there, when something conceptually similar (creating Components without rendering them) is happening.
Basically, both will serve the same purpose. But the real advantage of creating a component is its reusability.
If you have to render that particular piece of jsx just for this component. Then, there is no need to create a separate component.