How to signal to React that a functional component is "pure", as an equivalent of React.PureComponent for component classes?
function C(props) {
return <var>{props.n}</var>
}
without making it a class
class C extends React.PureComponent {
render() {
return <var>{this.props.n}</var>
}
}
As of React 16.6.0, memo has been added, so the answer is now:
const C = React.memo(props => {
return <var>{props.n}</var>
})
Based on the concept of purity in functional programming paradigms, a function is pure if:
Its return value is only determined by its input values
Its return value is always the same for the same input values
There seem two ways to do it for React functional components:
Using memo from react:
import React, { memo } from 'react';
const Component = (props) {
return (
// Component code
)
}
// Wrap component using "memo" HOC
export default memo(Component);
Using pure from recompose:
import React from 'react';
import { pure } from 'recompose';
const Component = (props) {
return (
// Component code
)
}
// Wrap component using "pure" HOC
export default pure(Component);
To #Shubham and #Andrew:
No, functional components are not PureComponents. Functional components will always get re-render if the parent component re-renders. A PureComponent contains a default shouldComponentUpdate() and I think that's what OP wants.
You can use pure provided by recompose to wrap and optimize your functional components:
import pure from 'recompose/pure'
const YourFunctionalComponent = (props) => {
...
}
export default pure(YourFunctionalComponent)
In addition to CodinCat answer.
The author of the library, recomponse, wrote a note on 25th Oct of 2018, where he stated, that what he tried to solve by the library was solved by the React Team through introducing hooks. Not only that, React team added optimization feature like React.memo(), which was named as React.pure() earlier. So, it's time to use React.memo(). Read Official Docs about it
Related
ReactJS is a great library, However, it misses some features which I found in Vue and Angular. These features can be implemented of course in React, however, they require extra code to be written.
Every react component, or every JSX element I should say has the following properties shared, which are given by React to us to consume:
ref
key
I wanted to add extra props:
renderIf
fallback
These props help in a way I can't describe when it comes to conditional rendering and filtering the views based on the logged-in user permissions and roles (and other conditional rendering use cases, of course).
In react, if we wanted to apply these props to our components, we would use a HOC as follows:
// 🍎 Disclaimer: you don't have to understand any of the code written bellow, the general idea is that this is a HOC.
import React from 'react'
import getVal from './getVal'
export default function EnhancedComponent(OriginalComponent) {
return ({ renderIf: renderIf_ = true, override: override_, fallback: fallback_ = undefined, ...props }) => {
const renderIf = getVal(renderIf_)
const override = getVal(override_)
const fallback = getVal(fallback_)
const consumersComponent = <OriginalComponent {...props} />
let render = fallback
if (renderIf) render = consumersComponent
if (override_ !== undefined) render = override
return render
}
}
Where every time you want to apply these props to your components, you would have to wrap every new component you create with EnhancedComponent as follows:
export default EnhancedComponent(function Sidenav(){
return <div> side nav </div>
})
Now, you can use your Sidenav component within your App component as follows:
import Sidenav from './Sidenav'
export default function App(){
return (
<div>
<Sidenav renderIf={(5 + 5 === 10)}/>
<div>etc</div>
</div>
)
}
This API is great, but it has a drawback, which is, every time you want to apply these cool props (renderIf and fallback) you'll have to repeat these steps:
import Enhanced component to your file.
wrap your export with Enhanced component.
What I am looking for, is a method, or a way to inherit, or to add some props to the original react component class, somehow?
In react class components, I can imagine doing this on the React.Component class which we used to extend from in the past
class Car extends React.Component{
constructor(){}
render(){
return <div>I miss you 🌹</div>
}
}
But in react functional component, how can we do that?
I want to apply these props by default everytime I create a new component, without wrapping my components in a HOC everytime.
Does React have a way to do that? To change its defaults ?
Writing unit testing in react using jest and enzyme. While checking with a component state , it throws an error "ReactWrapper::state() can only be called on class components ".
import React from 'react';
import { mount } from 'enzyme';
import expect from 'expect';
import CustomerAdd from '../CustomerAdd'
import MUITheme from '../../../../Utilities/MUITheme';
import { ThemeProvider } from '#material-ui/styles';
describe('<CustomerAdd />', () => {
const wrapper = mount(
<ThemeProvider theme={MUITheme}>
<CustomerAdd {...mockProps}></CustomerAdd>
</ThemeProvider>
);
test('something', () => {
expect(wrapper.find(CustomerAdd).state('addNewOnSubmit')).toEqual(true);
});
});
In the above code CustomerAdd Component is class component.I don't what wrong with my code. Can any one help me out of this problem. Thanks in advance.
So your default export
export default withStyles(styles)(CustomerAdd);
exports functional(HOC) wrapper about your class-based component. And it does not matter if name of class and import in
import CustomerAdd from '../CustomerAdd'
are equal. Your test imports wrapped version and after calling .find(CustomerAdd) returns that HOC not your class. And you're unable to work with instance.
Short time solution: export class directly as named export.
export class CustomerAdd extends React.Component{
...
}
export default withStyles(styles)(CustomerAdd);
Use named import in your tests:
import { CustomerAdd } from '../CusomerAdd';
Quick'n'dirty solution: use .dive to access your underlying class-based component:
expect(wrapper.find(CustomerAdd).dive().state('addNewOnSubmit')).toEqual(true);
It's rather antipattern since if you add any additional HOC in your default export you will need to monkey-patch all related tests with adding appropriate amount of .dive().dive()....dive() calls.
Long-term solution: avoid testing state, it's implementation details.
Instead focus on validating what's been rendered. Then you are safe in case of lot of different refactoring technics like replacing class with functional component, renaming state/instance members, lifting state up, connecting component to Redux etc.
I'm asking myself if the React.memo is exactly the same as recompose pure() ...
import { pure } from 'recompose';
export default pure(MyComp);
or
import React, { memo } from 'react';
export default memo(MyComp);
Any thoughts?
According to the React documentation.
React.memo is a higher order component. It’s similar to React.PureComponent but for function components instead of classes.
So they are not exactly the same, but they serve the same purpose.
I'm beginning to switch to functional/stateless components in React, like the one below.
I do however have a problem with react-chartjs-2 re-drawing my charts, even though the data for them didn't change. Before I switched to functional components, this was easily solved by using Reacts PureComponent.
Is there a way to make React use the PureComponent for a stateless function?
const ListGroup = props => {
const {title, width} = (props);
return (
<ul className={"grid"} style={{width}}>
<h1>{title}</h1>
{props.children}
</ul>
)
}
Since React v16.6.0 you can use React.memo():
import React from 'react';
const PureListGroup = React.memo(ListGroup);
With React versions before v16.6.0, You can use recompose (discontinued but still maintained) and wrap the component with the pure or onlyUpdateForKeys higher order components:
import pure from 'recompose/pure';
const PureListGroup = pure(ListGroup);
I'm new to ES6 and Redux. Im looking at some code and trying to understand what is going on in this new ES6 syntax.
I feel like this may be simple but i am not understanding it and it might help someone else in a similar position to me.
i want to know how the following code is creating a react element. im familiar with the React.createClass method, but that doesnt seem to be stated here or at least not explicitly. i can see React is imported, but it isnt mentioned in the rest of the code. so then how the FileTable get turned into a react component?
I can see the const variable FileTable seems to contain what would usually go in the render method of React.createClass, but if that is the case, where would methods like componentDidMount, componentDidUpdate, etc be defined?
Any help on this is greatly appreciated.
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';
const FileTable = ({ fileList, getFileList}) => {
return (
<ul className="filterable-table">
{fileList.map((file)=><li>{file.fileName}</li>)}
</ul>
);
};
FileTable.propTypes = {
fileList: PropTypes.array,
};
const mapStateToProps = (state) => {
return {
fileList: state.fileList
};
};
const mapDispatchToProps = (dispatch) => {
return {
getFileList: () => dispatch(actions.getFileList())
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(FileTable);
You can create react components in 3 ways - React.createClass, ES6 class or
Stateless (pure) function component. This is a stateless component, which means that it doesn't have state, life cycle methods (like componentDidMount or componentDidUpdate), and refs, and as you surmised it's similar to the render method of a react class.
Whenever you need a purely representational dumb component you can use a stateless component, due to its brevity. It goes nicely with redux, as the connect create a smart component that wraps the stateless method.
Regarding performance, stateless components don't have any performance gain over ES6 class component without state. However, Facebook stated that in the future there will be some optimizations.
It doesn't have to be declared here as a React component; React knows about pure functions.
Pure functions don't need to inherit from Component. They're not appropriate for all component types, but for simple HTML renders they're preferred (e.g., see eslint-plugin-react prefer-stateless-function.
Pure functions don't have component lifecycles, associated methods, etc.