Getting more and more into the awesomeness that is React.js and I've started to use Mixins more.
One thing I noticed, is that both my mixin and my component can have a componentDidMount method — And both functions will be called, so defining it in the component won't override the one in the mixin and vice versa.
Here's an example:
var MyMixin = {
componentDidMount: function() {
// Do something when component is mounted
console.log("Mixin fn ran");
}
};
var Component = React.createClass({
mixins: [MyMixin],
componentDidMount: function() {
// Do something when component is mounted
console.log("Component fn ran");
}
});
Now, the question is wether this is by design or just a coincidence that this works. The lifecycle methods are very useful (To bind and unbind events for instance), so it's not uncommon that both my component and mixins will want to rely on those. The documentation doesn't say anything about this, and I'm wanting to know if I'm setting myself up for a bad time down the road by doing this.
Another question is do I have some kind of control over which method is called first? The one in the mixin or the one in the component.
Yes, it's intentional, and the main factor that makes mixins very powerful in React.
So what happens is:
for the 'component...' functions, they're called in the order of mixin[0], mixins[1], ..., component
propTypes, and the return value of getInitialState and getDefaultProps are merged
other conflicting method names, or conflicts while merging the above results in an error
Related
I'm converting a React ES6 class-style component to a functional component. The one thing I'm slightly unsure of is how best to convert private class methods. As far as I can tell, I should convert them to functions within the functional component's function, as they need to be there to access the component's state. However, that presumably means that on each re-render, the function is going to get recreated:
Before
class Game extends React.Component {
handleClick(i) { if (this.state.foo) { ... } }
}
After
function Game {
function handleClick(i) { if (foo) { ... } }
}
Is this a problem performance-wise, and if so, is there any way to improve it?
Also, most guides I've read recommend assigning arrow functions to variables instead of just declaring functions, eg.
function Game {
const handleClick = (i) => { if (foo) { ... } }
}
Is this purely stylistic, or is there another reason to use assigned arrow functions over regular nested function definitions?
You can use functions defined with either the function keyword or the arrow function syntax. It does not really make a difference in this case. However, with the arrow syntax, functions do not get hoisted, and that may cause the linter to report a warning if you use a function before it is defined.
However, that presumably means that on each re-render, the function is
going to get recreated
You are correct, if you define functions either way, they will get recreated on every re-render. Whether that's a problem or not will depend on your use case.
If you use such a function inside a useEffect callback and add it to its dependency array, the effect will re-run on every re-render (which may not be what you want). If you pass such a function as a prop to any child component(s), that component(s) will also re-render.
You can wrap the functions in question with useCallback, and any child components that receive these as props with React.memo. However, you are now trading the cost of re-rendering components for the cost of storing and comparing props (React will be doing this, not you).
So really, this depends on your app. If the component in question has a large component tree below it, going with useCallback and React.memo might be worth it.
I have a container that I need to change the UI form showing the form or showing a success page.
The container has a state.showSuccess and I need the MyFormModule to be able to call the container to change the state.
The below code works but I'm getting the following warning:
JSX props should not use .bind()
How can I get this to work without using .bind()?
...
const myPage = class extends React.Component {
state = { showSuccess: false };
showSuccess() {
this.setState({
showSuccess: true,
});
}
render() {
const { showSuccess } = this.state;
if (showSuccess) {...}
....
<MyFormModule showSuccess={this.showSuccess.bind(this)} />
You should first understand WHY this is a bad practice.
The main reason here, is that .bind is returning a new function reference.
This will happen on each render call, which may lead to a performance hit.
You got 2 options:
Use the constructor to bind your handlers (this will run only once).
constructor(props) {
super(props);
this.showSuccess = this.showSuccess.bind(this);
}
Or create your handlers with arrow functions so they will use the
lexical context for this, hence you won't need to bind them at
all (you will need a babel plugin):
showSuccess = () => {
this.setState({
showSuccess: true,
});
}
You should not use this pattern (as others suggested):
showSuccess={() => this.showSuccess()}
Because this will as well create a new function on each render.
So you may bypass the warning but you are still writing your code in a bad practice design.
From the ESLint docs:
A bind call or arrow function in a JSX prop will create a brand new
function on every single render. This is bad for performance, as it
will result in the garbage collector being invoked way more than is
necessary. It may also cause unnecessary re-renders if a brand new
function is passed as a prop to a component that uses reference
equality check on the prop to determine if it should update.
Use an arrow function when defining showSuccess
showSuccess = () => {
this.setState({
showSuccess: true,
});
}
Use an arrow function since they automatically inherit the this context of wherever they are defined.
showSuccess={() => this.showSuccess()}
Here is a link to the facebook documentation on this subject, which lists this method among others as a solution. Interestingly, they also list using .bind in the prop as one of the solutions, even though it produces a warning when actually used.
From that documentation, you'll note that this is a potential performance issue, since the function will be recreated on every render:
Note:
Using an arrow function in render creates a new function each time the
component renders, which may have performance implications (see
below).
But also from the same link:
Is it OK to use arrow functions in render methods? Generally speaking,
yes, it is OK, and it is often the easiest way to pass parameters to
callback functions.
If you do have performance issues, by all means, optimize!
So I would say if your component will be re-rendering very frequently, you should use one of the other solutions: bind in the constructor, or define the method with an arrow function in the first place. But if not, use whatever method seems cleanest to you.
Say I want to create a Simple React component with some methods (no state or life-cycle methods). I can do it one of two ways:
// Foo.js
class Foo extends React.Component {
doSomething() {
// do something
}
render() {
...
this.doSomething();
...
}
}
export default Foo;
Or I can do it like this:
// Foo.js
const doSomething = () => {
// do something...
}
const Foo = () => {
...
doSomething();
...
}
export default Foo;
The second is preferable because it's a functional component (simpler, less overhead), but does the closure function come with any overhead / risk of memory leaks?
In general, if a component doesn't keep state or use life-cycle methods, which is the preferable way to implement the component?
Generally, if you:
Do not want to maintain state
Don't need to use lifecycle methods ( like componentDidMount )
it's better to use stateless functional components, which are fast and more readable. And no, you needn't worry about memory leaks due to closure. For more benefits of stateless components, see https://hackernoon.com/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc
There is no need to use class-based components if you are not keeping track of application state or life-cycle methods simply because it is a lot of overhead, and you don't need to keep track of the this keyword, which is frankly, annoying.
A functional component is dumb. It has no idea of the application state at all. It can be used to display / present the component without having to worry about updating itself when an event is emitted.
In your case, if the doSomething() method does not involve any dynamic behavior, it is preferable to go with the second approach.
I have been working with the Component Factory Resolver for awhile and while I think it's pretty slick, there is one thing that drives me nuts. I would love to wrap most of the repeated code into a helper function that renders the component.
In my case I have a dashboard component where we render quite a few different components by altering singleton services to trigger visibility or not. Rather than having a ton of these create component code blocks, I was wondering if anyone has successfully create a helper-like function that a few variables can be passed into to achieve the same effect, thus eliminating a lot of the repetitive code.
Below is my attempt at a helper function and the call to activate it. The component gets created, but the destroy function doesn't work. I have narrowed it down to the Component Reference not actually being saved to the globally accessible component. Is there a way to store component references within a global array? If so how would you go about dynamically accessing them as components are added/destroyed?
Subscription within ngOnInit
// Subscribe to Create User Modal Visibility
this._ComponentVisibilityService.createUserVisibility$.subscribe(
_createUserVisibility => {
this.renderComponent(
this.createUserModal,
CreateUserComponent,
this.createUserModalContainer,
_createUserVisibility
)
}
)
Function within the dashboard component
renderComponent(component, template, container, visibility) {
if (visibility) {
// Destroy previously built components if not already destroyed
if (component) component.destroy();
// Generate component factory
const componentFactory = this._ComponentFactoryResolver.resolveComponentFactory(template);
// Render the component
component = container.createComponent(componentFactory);
} else {
// Destroy the component if visibility is false
if (component) component.destroy()
}
}
So ended up doing some digging last night and found that Typescript considers any to be a basic (primitive) type. So from what I can tell, none of the methods, or structure are available to component, unless altered to not fit into the "basic" category, otherwise its passed as a value and not a reference. However, like in javascript, an object is not considered a primitive type so I refactored the component variable to be cast as an object with a property component as ComponentRef<any>, and it worked!
Component Property Declaration
createUserModal: { component: ComponentRef<any> } = { component: null }
Function Declaration
renderModal(component: { component: ComponentRef<any> }, template, container, visibility) {
// Create Component...
}
This combination allows the object to passed in as a reference which in turn allows the function to alter the value of DashboardComponent property this.createUserModal, which in turn allows all of the methods to be called on it as normal.
You're not supposed to use anonymous functions in react attributes, e.g.
<a onClick=()=>doIt('myId')>Aaron</a>
I understand why this creates a performance problem for React's reconciliation because that anonymous function is recreated on every render pass and will thus always trigger a real DOM re-render of some kind. My question is, for a small component (i.e. not table where every row has a link) is this insignificant? I mean, React is smart enough just to replace the handler, not to re-render the DOM, right? so the cost is not that high?
I feel obliged to inform you that using an Anonymous function and Function.bind(this) in the render triggers a new render. This is because both
doIt.bind(this, 'myId') === doIt.bind(this, 'myId') // false
AND
() => doIt('myId') === () => doIt('myId') // false
are FALSE!
If you want to bind something to a function, use partial application with a method in the React class.
class myComponent extends Component {
doIt = (id) => () => {
// Do Something
}
render() {
<div>
<a onClick={this.doIt('myId')}>Aaron</a>
</div>
}
}
For:
small components: you are ok (almost no performance issues)
large components: the deeper you get the more try to avoid it
In React documentation about event handling, you can find:
In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.
Note: React is not handling callback props differently than other props. It always compares the old and new prop. Thus it re-renders when anonymous function is present because the anonymous function is always newly created.
Your JSX code sample should actually look like this:
<a onClick={ ()=>doIt('myId') }>Aaron</a>
Using an anonymous fat arrow function like this is perfectly valid. You are supposed to use anonymous functions in react attributes. That's okay.
Yes, it's not a best practice. If you want to solve the this context issue when using the ES6 class extends React.Component syntax I would advise you to bind the function in the class constructor.
No, for a 'small' component (i.e. not table where every row has a link) this is not a significant performance issue. You are safe.