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.
Related
I'm new to ReactJs and trying to follow best practices. From my research, I've come across a couple of contradicting articles discussing how implementation should be.
Should state rely on the properties being passed down from a parent component? In the comparisons below, they are both following SRP, but not sure which is best. Would like your advice, Thanks!
1. -- Best Practices for Component State in React.js
First, and probably the most important of all, the state of a component should not depend on the props passed in. (see below for example of what we should not do)
class UserWidget extends React.Component {
// ...
// BAD: set this.state.fullName with values received through props
constructor (props) {
this.state = {
fullName: `${props.firstName} ${props.lastName}`
};
}
// ...
}
2. -- 7 architectural attributes of a reliable React component
Let's refactor to have one responsibility: render form fields and attach event handlers. It shouldn't know how to use storage directly.....The component receives the stored input value from a prop initialValue, and saves the input value using a prop function saveValue(newValue). These props are provided by withPersistence() HOC using props proxy technique.
class PersistentForm extends Component {
constructor(props) {
super(props);
this.state = { inputValue: props.initialValue };
}
// ...
}
3. -- In my case, I have something like the following (wondering if this is an acceptable implementation?) - Should state be handled in Tasks, or in another TasksWithPersistence type of component that sits between TasksWithData and Tasks?
export default function TasksWithData(TasksComponent) {
return class withData extends React.Component {
render() {
const tasks = TaskAPI.getTasks();
return (
<TasksComponent
tasks={tasks}
{...this.props}
/>
)
}
}
}
export default class Tasks extends React.Component {
state = {
tasks: [],
addItemInput: null
};
// ...
componentDidMount() {
this.updateComponentState({tasks: this.props.tasks});
}
componentDidUpdate() {
this.prepUIForNextAddition();
}
// ...
}
The gist of your question seems to revolve around the anti-pattern that is to take some props and duplicate it into the state. This, mutating of props, isn't the purpose of the state. Props are immutable, duping them to the state defeats this design.
The purpose of the state is to manage things that are specific to the React Component, i.e. tightly scoped to only that React component. For instance a showHide switch for something to display within the React component. Think of the state as a locally scoped variable if it helps.
Most of the time this anti-pattern of duping the props can be satisfied by a function within the React object. For example, your state.full_name variable becomes a named function, fullName, bound to the React Component. (all code examples are assuming JSX syntax)
Note: in JavaScript camelcase is the naming structure for functions and variables, I'm assuming you're coming from ruby based on the underscore naming convention. IMO it's best to stick to the convention of the language with which you're writing the code. This is why I use camelcased naming.
...
fullName() {
return this.props.firstName + " " + this.props.lastName
}
...
That function can then be called within the render of the component
# in render() portion of your React component, assuming jsx syntax
<p>Hello, {this.fullName()}</p>
Note: Remember that in ES6 you have to bind the methods in your react class in the constructor or use => syntax so that you can call them with this.
...
constructor(props) {
super(props);
this.fullName = this.fullName.bind(this);
}
...
You could also decompose the relevant parts to a new Component called FullName if it will be utilized by multiple components.
<FullName firstName={this.props.firstName} lastName={this.props.lastName} />
Technically, "the react way" is, at least in this author's opinion, to decompose this into another component for reusability. However component reuse needs to be weighed against the complexity added, i.e. don't optimize prematurely. So you may not want to take that too far at first. The times when it's necessary will emerge naturally.
A very broad generalization of React's props is that they are guaranteed, are immutable, and they flow down like a waterfall from the topmost component. If you need to update them, update them at the highest level where it makes sense.
In a soley React based approach, if you have something that a parent needs to be aware of, "lift" that part of the code up to the parent and vice versa bind it down to the child as a props, e.g. an AJAX function that calls an API. I think of it as trying to keep the components as dumb as possible.
The parent becomes the "source of truth" for the item you "lifted". The parent handles the updates, and then passes the results to the children. So in the parent, it may exist as a state variable and then get passed as props to the child object, which then passes it along as props to it's child object, etc. The children would update as the state gets changed in their parent when it propagates down through the chain as props.
If your app is React only, i.e. no stores that manage objects such as in the flux pattern or redux pattern, you may have to store things in the topmost objet's state which technically could be viewed as bad. As your system becomes more complex, this functionality would be better handled by flux or redux's parts.
Hope this helps!
There is a huge difference between example 1 & 2.
In example #1, the reason it's bad to set state from the those props in that way is that if the props change, the widget will not update. Best practices or not, that is just wrong and bad in any framework. In that particular case, there really is no point in even using the state. Props alone will suffice.
In example #2 the prop is only being used to give the state an initial value (The prop is even named initialValue), implying that further changes to the state will be controlled by the component regardless of prop changes. It does not break single responsibility principle to use props for an initial state, especially when it's explicitly use for that purpose.
I really don't see those two examples as being contradictory because they are completely different. Further, there is no rule in single responsibility principle that you can't set state from props, you just need to pay attention to the context in which you are doing it.
One thing I had learned about React is that if the props to a component don’t change, then React doesn’t bother re-rendering the component. Is that true for stateless components too? Or do they behave more like “stupid” functions and get executed every time?
For example, if I had:
import StatelessComponent from '../StatelessComponent';
export default class DocumentsTable extends React.Component {
state = {
something: 'foobar',
};
render() {
return (
<div>
{ this.state.something }
<StatelessComponent theOnlyProp='baz'>
</div>
)
}
};
When this.state.something updates its value, does <StatelessComponent> get re-rendered? Or is it “smart” enough to see that its props didn’t change, like other React components?
UPDATE 25.10.2018
Since React 16.6, you can use React.memo for functional components to prevent re-render, similarly to PureComponent for class components:
const MyComponent = React.memo((props) => {
return (
/* markup */
);
});
Also, memo does internal optimization.
And unlike a userland memo() higher-order component implementation, the one built into React can be more efficient by avoiding an extra component layer.
Blockquote
OLD ANSWER
Yes, they always re-render 1 (unless you use React.memo as explained above) if setState() is called in the component itself or one of its parents, because functional stateless components don't carry a shouldComponentUpdate. In fact, each React component is being re-rendered1 unless they implement shouldComponentUpdate.
Important to note is that calling render() doesn't mean that DOM Nodes are being manipulated in any way. The render method just serves the diff algorithm to decide which DOM Nodes need to really be attached / detached. Note that render() is not expensive, it's the DOM manipulations that are expensive. They are executed only if render() returns different virtual trees.
From React's documentation
Just to be clear, rerender in this context means calling render for all components, it doesn’t mean React will unmount and remount them. It will only apply the differences following the rules stated in the previous sections.
Just don't worry and let render() be called unless your component is huge, then you're better off with stateful Component that implements shouldComponentUpdate().
Look here for an interesting discussion.
1 means that render() function of the component is called, not that the underlying DOM node is being manipulated.
See react does not only rerenders only If props are changed it even rerenders itself if any state change is there. In your case the component will rerender as your state is changing. The way react works is based on an algorithm named Reconciliation, what this algorithm does is that it compares your virtual DOM with real DOM and if it sees any change then it rerender your actual DOM by replacing it with your virtual DOM so any change in state will cause rerendering of the whole component.
Will a Stateless component re-render if its props have not changed?
Yes. Stateless render function will be called even if nothing has changed. However, React will in the reconciliation phase compare the virtual DOM (generated by the render function) against the existing DOM. This is far in the pipeline, hence not ideal if the render function was costly to compute.
A Pure component does have a default shallow comparison of the property and would have stopped the render to be executed. See the Pure component as a normal class React component that has a shouldComponentUpdate that compare with a triple equal the existing properties and the new one.
That being said, you can wrap your Stateless component into a Pure Component by using Recompose.pure (https://github.com/acdlite/recompose/blob/master/docs/API.md#pure) which will automatically perform, like the Pure Component, a shallow comparison without compromising on the short syntax of the Stateless component.
import StatelessComponent from '../StatelessComponent';
const PureChildFromStatelessComponent = Recompose.pure(StatelessComponent);
// ...
<PureChildFromStatelessComponent ... />
In React quickstart, it is stated about Refs and Functional Components that
You may not use the ref attribute on functional components because
they don't have instances:
function MyFunctionalComponent() {
return <input />;
}
class Parent extends React.Component {
render() {
// This will *not* work!
return (
<MyFunctionalComponent
ref={(input) => { this.textInput = input; }} />
);
}
}
I don't fully understand the above statement and the example. So far from reading the tutorials, the only difference between functional and class component is that the latter can have things like constructor and lifecycle management functions.
What does the documentation mean when it says functional components don't have instances? Is it because they don't have this pointer? Is this restriction coming from react or ES6?
React class components extend React.component which is a JS class. They are instances of React.component and inherit features like lifecycle hooks and internal state management from React.component itself. In this sense, I would call them components which have an instance, since React will use the same React.component instance to persist component state during its lifecycle.
React function components are nothing but JS functions: they get a set of properties as input and output a piece of virtual DOM. These functions are re-executed from top to bottom each time React decides the resulting virtual DOM might be out of date. Since plain JS functions don't persist any state by design, state persistence is delegated to a few global React API called hooks.
I faced the same doubt while reading the docs on ref. However, after doing a little more research I found this discussion. (https://github.com/facebook/react/issues/4936#issuecomment-142379068)
Functional components don't have instances because they are mere JS functions. A function can't have an instance. Whereas, classes have instances(objects) of them.
So when the documentation says you can't use ref on functional components because they don't have instances means that -> how can you store the instance of a functional component when it doesn't exist?
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.
What is the different between states and props?
How can you pass a value of let's say CompomentA to ComponentB if we have have for example ComponentA which takes an input then ComponentB is suppose to output(to print it on the screen) that same value if we have a third component called CompomentContainer which is a container of both A and B?
What is Redux? the definition of redux on the main website does not make sense to me. How does it work exactly? How is it useful to react?
Please bear with me, I hope my questions make sense. Thank you.
Those are very valid questions. I've been there and I know how frustrating it is to read about redux and not understanding anything. For some reason people like to use fancy words, which sounds complicated but in reality things are very simple and easy.
What is Redux?
Redux is a Flux architecture. In simple words it will help you to manage the global state of your app.
How does it work exactly?
Redux will create a single "store", this store will have all the data that you need to render in your components, you can update the data using "actions", you will call the actions from your components, these actions will transfer the new data to the "reducers", inside of a reducer you will basically copy the data from the components to the global state (reducers should be pure functions).
How is it useful to react?
It's very useful! Mainly because you will be able to share data across components. Also by having a global state you could save it to the local storage (or a database) to add offline support.
What is the different between states and props?
You can define props to describe the properties that the component will receive when creating instances, you can think of props like parameters, for example:
<MyComponent name="Crysfel" lastname="Villa" />
The previous component is receiving two props, name and lastname. Props will allow you to send data from ComponentA to ComponentB, assuming ComponentB is a child of ComponentA. Props will also help you to receive data from redux. As a rule of thumb, you should never modify the value of the props, these values are just to receive data.
State on the other hand is an object that might contain configurations for your component, the idea is to handle the state of the component, for example a collapsible container, you could have a toggle property in the component's state and toggle the value when user clicks a button. However when using redux you will rarely use the component's state, because Redux is managing the state of your app.
For your second question about sending data between component, you would use redux for that, ComponentA should call an action and send the new data to the global state, then redux will update your component with the new data and then you can render the new data into ComponentB (using props).
What is the different between states and props?
State is data that is tied directly to the React component in which it is set. Props is data that is passed into a child component from the parent component. Unlike state, props are immutable and never "set" directly.
How can you pass a value of let's say CompomentA to ComponentB if we have have for example ComponentA which takes an input then ComponentB is suppose to output(to print it on the screen) that same value if we have a third component called CompomentContainer which is a container of both A and B?
To pass value from Component A to ComponentB you would provide the value as props, passed in via the ComponentA render function. Something like this:
class ComponentA extends React.component {
render() {
return <ComponentB myvalue={value} />
}
}
In ComponentB the value can be accessed: this.props.myvalue
What is Redux? the definition of redux on the main website does not make sense to me. How does it work exactly? How is it useful to react?
Redux is an implementation of the ideas of Flux with a few architectural differences. You can think of it as a library that helps you create a central data store that passes data one-way into React components. It allows you to maintain global state outside of the components themselves.
A top-level container component typically listens to the store and re-renders whenever the store data changes (see the connect function). The data is then passed from the container component into the children components that need that data so they can render properly.