i try to use and overwrite a parent method in child one but get Uncaught TypeError: Cannot read property 'call' of undefined
class BreadcrumbsHome extends React.Component {
getBreadcrumbs = () => [{name: 'home', url: '/'}];
render() {
return <nav>
<ol className="breadcrumb float-sm-right">
{!!this.getBreadcrumbs && this.getBreadcrumbs().map((e, i, arr) =>
<li className={`breadcrumb-item ${i === arr.length - 1 ? 'active' : ''}`}><a
href={APP_CONTEXT + e.url}>{e.name}</a>/</li>
)}
</ol>
</nav>
}
}
class BreadcrumbsTypes extends BreadcrumbsHome {
getBreadcrumbs = () => [
...super.getBreadcrumbs(),
...this.props.path
]
as i read about this problem. Seems to be tied with babel so i tried adding the //noprotect
line
I would like to handle with ES6 and avoid such way
ParentClass.prototype.myMethod.call(this, arg1, arg2, ..)
Any ideas to fix that?
If you want to maintain the typical virtual polymorphism expected in JavaScript prototypal inheritance, you can't use field initializer syntax, you must use the ES2015 class method syntax:
class BreadcrumbsHome extends React.Component {
getBreadcrumbs () {
return [{ name: 'home', url: '/' }];
}
render() {
return <nav>
<ol className="breadcrumb float-sm-right">
{this.getBreadcrumbs().map((e, i, { length }) => (
<li
key={`${e.name}-${e.url}`}
className={`breadcrumb-item ${i === length - 1 ? 'active' : ''}`}
>
<a href={APP_CONTEXT + e.url}>{e.name}</a> /
</li>
))}
</ol>
</nav>
}
}
class BreadcrumbsTypes extends BreadcrumbsHome {
getBreadcrumbs () {
return [
...super.getBreadcrumbs(),
...this.props.path
];
}
...
}
The problem is that field initializers create own properties on each class instance rather than binding to the prototype chain like class methods do, so all you were doing was overwriting the own property getBreadcrumbs
initialized by the base class with the own property initialized by the extended class.
You can confirm this using a debugger console:
P.S. don't forget to include a unique key
property on mapped JSX components :)
I'd also suggest using CSS to style .breadcrumb-item:last-child
rather than .breadcrumb-item.active
, so your map()
callback can simplify the className
to
className="breadcrumb-item"
You can also add the following class to your CSS
.breadcrumb-item::after {
content: "/";
}
so you can omit the /
in your JSX.