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.
Related
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.
We are having a discussion at work on what is the best practice for using with the redux connect function. Should we use the presentational component or the container component it's self by putting the presentation component inside the container component. I see some example online where people are putting the presentation component inside a container and some places outside the container It would be great if someone could tell the best practice.
I'm a Redux maintainer.
I would advise that you should default to defining both your plain component and the connect wrapper in the same file, for simplicity:
import React, {Component} from "react";
import {connect} from "react-redux";
import {addTodo, toggleTodo} from "./todos";
const mapState = (state) => ({todos: state.todos});
const mapDispatch = {addTodo, toggleTodo};
// Named export for the class
export class TodoList extends React.Component { /* */}
// Default export for the connected component
export default connect(mapState, mapDispatch)(TodoList);
Similarly, I would recommend going with a "feature folder"-type approach for structuring your files.
I have a saved chat log where I give my thoughts on the whole "container" and "presentational" concept that you might find useful. Similarly, note that Dan Abramov no longer recommends splitting "container" and "presentational" components.
I am going through some react code, can any one please let me know what does default as React in below code does.
import {
default as React,
Component,
PropTypes,
} from "react";
Thanks,
Guru
what is default in react import?
Default in that context is the entire React library. It is unnecessary in this case and could be shortened to import React, { Component } from 'react'
Another thing to note, is that proptypes have been moved to their own package now.
That's the same as:
import React, { Component, Proptype } from 'react';
obs: Since react v15.5 React.PropTypes has moved into a different package
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
This is so simple I hate to ask it, but after searching the react router docs and googling around I have found nothing. I have a component that is wrapped using withRouter when it is exported:
export default withRouter(MyComponent)
I want to test this component but I am getting the following when testing:
<Login router={[undefined]} />
I usually just import my components to test them individually using enzyme's shallow method. Is there a way to unwrap this component so I can import it for testing?
You will just need to export that component as well:
export const MyComponent
and in your test:
import { MyComponent } from '../src/components/MyComponent'