React.js onClick event: TypeError: Cannot read property of undefined
React.js onClick event: TypeError: Cannot read property of undefined
目前在学习 React 和 JavaScript 时遇到困难。
我有两个组件,导航:
import React from 'react';
import ReactDOM from 'react-dom';
import Nav from './houses/Nav.js';
// set data
var navbar = {};
navbar.brand = {linkTo: "#hero", text: "text"};
navbar.links = [
{linkTo: "#", event:"es", spanClassName: "flag-icon flag-icon-es"},
{linkTo: "#", event:"en", spanClassName: "flag-icon flag-icon-gb"},
{linkTo: "#about", text: "about", spanClassName: "btnicon icon-user"},
{linkTo: "#contacts", text: "contacts", spanClassName: "btnicon icon-envelope-open"}
];
class Navigation extends React.Component {
render() {
return (
<header>
<Nav {...navbar} />
</header>
)
}
}
module.exports = Navigation;
和Nav:
import React from 'react';
import ReactDOM from 'react-dom';
class Nav extends React.Component {
render() {
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
}
return(
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
<span className="sr-only" lang="lt">Toggle nav</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
</div>
<div className="collapse navbar-collapse">
<NavMenu links={this.props.links} />
</div>
</div>
</nav>
);
}
};
class NavBrand extends React.Component{
render() {
return (
<a className="navbar-brand" alt="back to home" href={this.props.linkTo}>{this.props.text}
<span className="brandicon"></span>
<span className="brandname"></span>
</a>
);
}
};
class NavMenu extends React.Component{
render() {
var links = this.props.links.map(function(link){
return (
<NavLink linkTo={link.linkTo} text={link.text} active={link.active} event={link.event} spanClassName={link.spanClassName} />
);
});
return (
<ul className="nav navbar-nav navbar-right">
{links}
</ul>
);
}
};
class NavLink extends React.Component{
render() {
if (this.props.event){
return(
<li><button onClick={() => changeLanguage(this.props.event)}>{this.props.event}<span className={(this.props.spanClassName)}></span></button></li>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
module.exports = Nav;
目前我只想将自定义 onClick 事件添加到具有语言属性的特定 <li>
元素。它应该呈现这个:
其他组件的 render() 中的 onClick 事件看起来像这样:
onClick={() => changeLanguage('lang_attribute')}
所以我应该得到相同的结果,但通过导航 render
按下呈现的按钮我收到错误消息:Uncaught TypeError: Cannot read property 'changeLanguage' of undefined
需要一些工作示例的帮助
更新
看来我的问题主要与 18next 有关。我正在研究 i18n 文档(因为另外我必须为菜单项进行翻译)并进行了一些尝试,但据我了解问题出在 HOC 和 i18n 函数上。它们超出了范围,因为这里有几个 类。
所以我收到两个错误:t 不是函数,i18n 未定义。
import React from 'react';
import ReactDOM from 'react-dom';
import {translate} from 'react-i18next';
class Nav extends React.Component {
render() {
return(
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
<span className="sr-only">Toggle</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
</div>
<div className="collapse navbar-collapse">
<NavMenu links={this.props.links} />
</div>
</div>
</nav>
);
}
};
class NavBrand extends React.Component{
render() {
return (
<a className="navbar-brand" alt="back to home" href={this.props.linkTo}>{this.props.text}
<span className="brandicon"></span>
<span className="brandname"></span>
</a>
);
}
};
class NavMenu extends React.Component{
render() {
const { t, i18n } = this.props;
var links = this.props.links.map(function(link, index){
return (
<PureNavLink linkTo={link.linkTo} text={t(link.text)} active={link.active} event={link.event} spanClassName={link.spanClassName} />
/*text={t(link.text)}*/
);
});
return (
<ul className="nav navbar-nav navbar-right">
{links}
</ul>
);
}
};
class PureNavLink extends React.Component{
render() {
const { t, i18n } = this.props;
const toggle = lng => i18n.changeLanguage(lng);
if (this.props.event){
return(
<div>
<button onClick={() => toggle(this.props.event)}>{t(this.props.event)}</button>
</div>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
const NavLink = translate()(PureNavLink);
module.exports = translate()(Nav);
所以看起来您在 Nav
的 render()
方法中定义了 changeLanguage
函数。因此,changeLanguage
绑定到 Nav
的范围和上下文,因此您的 NavLink
组件对此一无所知。首先尝试将 changeLanguage
移出任何组件,然后查看它是否被调用,即
// define the function outside of component scope
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
// function is now available for use in any component in
// this module - just export it to use it in other modules
class Nav extends React.Component {
render() {
// your code and other components
}
}
React 组件中定义的方法和函数绑定到该组件的实例。在别处调用该函数或方法的唯一方法是 1) 在任何组件外部定义该函数,或 2) 将函数或方法的引用作为 prop
传递给您的子组件。如果执行第 2 点,请务必绑定原始组件的 this
上下文,否则您会收到如您所见的错误。
帕克的回答是正确的
a) 像上面的代码一样移动 changeLanguage - 但也 import i18n from '../i18n';
或者你定义 i18n 实例的地方。
import i18n from 'i18n';
// define the function outside of component scope
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
// function is now available for use in any component in
// this module - just export it to use it in other modules
class Nav extends React.Component {
render() {
// your code and other components
}
}
或者 b) 通过 props 向下传递 changeLanguage。
// ...
<NavMenu links={this.props.links} changeLanguage={changeLanguage} />
// ...
<NavLink changeLanguage={changeLanguage} linkTo={link.linkTo} text={link.text} active={link.active} event={link.event} spanClassName={link.spanClassName} />
或者 c) 用 translate hoc
装饰你的 NavLink
class PureNavLink extends React.Component{
render() {
const { t, i18n } = this.props;
const toggle = lng => i18n.changeLanguage(lng);
if (this.props.event){
return(
<div>
<button onClick={() => toggle(this.props.event)}>{t(this.props.event)}</button>
</div>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
const NavLink = translate()(PureNavLink);
https://react.i18next.com/components/translate-hoc.html.
或者 d) 使用 render prop I18n https://react.i18next.com/components/i18n-render-prop.html
//file.js
import { useTranslation, withTranslation, Trans } from 'react-i18next';
class myClass extends Component{
//...
componentDidMount() {
this.changeLanguage('de'); // en | fr
}
changeLanguage = (lng) => {
const { t , i18n} = this.props;
i18n.changeLanguage(lng);
};
render(){
//...
}
}
export default withTranslation()(myClass) // <-- this should solve the issue
目前在学习 React 和 JavaScript 时遇到困难。
我有两个组件,导航:
import React from 'react';
import ReactDOM from 'react-dom';
import Nav from './houses/Nav.js';
// set data
var navbar = {};
navbar.brand = {linkTo: "#hero", text: "text"};
navbar.links = [
{linkTo: "#", event:"es", spanClassName: "flag-icon flag-icon-es"},
{linkTo: "#", event:"en", spanClassName: "flag-icon flag-icon-gb"},
{linkTo: "#about", text: "about", spanClassName: "btnicon icon-user"},
{linkTo: "#contacts", text: "contacts", spanClassName: "btnicon icon-envelope-open"}
];
class Navigation extends React.Component {
render() {
return (
<header>
<Nav {...navbar} />
</header>
)
}
}
module.exports = Navigation;
和Nav:
import React from 'react';
import ReactDOM from 'react-dom';
class Nav extends React.Component {
render() {
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
}
return(
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
<span className="sr-only" lang="lt">Toggle nav</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
</div>
<div className="collapse navbar-collapse">
<NavMenu links={this.props.links} />
</div>
</div>
</nav>
);
}
};
class NavBrand extends React.Component{
render() {
return (
<a className="navbar-brand" alt="back to home" href={this.props.linkTo}>{this.props.text}
<span className="brandicon"></span>
<span className="brandname"></span>
</a>
);
}
};
class NavMenu extends React.Component{
render() {
var links = this.props.links.map(function(link){
return (
<NavLink linkTo={link.linkTo} text={link.text} active={link.active} event={link.event} spanClassName={link.spanClassName} />
);
});
return (
<ul className="nav navbar-nav navbar-right">
{links}
</ul>
);
}
};
class NavLink extends React.Component{
render() {
if (this.props.event){
return(
<li><button onClick={() => changeLanguage(this.props.event)}>{this.props.event}<span className={(this.props.spanClassName)}></span></button></li>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
module.exports = Nav;
目前我只想将自定义 onClick 事件添加到具有语言属性的特定 <li>
元素。它应该呈现这个:
其他组件的 render() 中的 onClick 事件看起来像这样:
onClick={() => changeLanguage('lang_attribute')}
所以我应该得到相同的结果,但通过导航 render
按下呈现的按钮我收到错误消息:Uncaught TypeError: Cannot read property 'changeLanguage' of undefined
需要一些工作示例的帮助
更新 看来我的问题主要与 18next 有关。我正在研究 i18n 文档(因为另外我必须为菜单项进行翻译)并进行了一些尝试,但据我了解问题出在 HOC 和 i18n 函数上。它们超出了范围,因为这里有几个 类。 所以我收到两个错误:t 不是函数,i18n 未定义。
import React from 'react';
import ReactDOM from 'react-dom';
import {translate} from 'react-i18next';
class Nav extends React.Component {
render() {
return(
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div className="container">
<div className="navbar-header">
<button type="button" className="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse" aria-expanded="false">
<span className="sr-only">Toggle</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<NavBrand linkTo={this.props.brand.linkTo} text={this.props.brand.text} />
</div>
<div className="collapse navbar-collapse">
<NavMenu links={this.props.links} />
</div>
</div>
</nav>
);
}
};
class NavBrand extends React.Component{
render() {
return (
<a className="navbar-brand" alt="back to home" href={this.props.linkTo}>{this.props.text}
<span className="brandicon"></span>
<span className="brandname"></span>
</a>
);
}
};
class NavMenu extends React.Component{
render() {
const { t, i18n } = this.props;
var links = this.props.links.map(function(link, index){
return (
<PureNavLink linkTo={link.linkTo} text={t(link.text)} active={link.active} event={link.event} spanClassName={link.spanClassName} />
/*text={t(link.text)}*/
);
});
return (
<ul className="nav navbar-nav navbar-right">
{links}
</ul>
);
}
};
class PureNavLink extends React.Component{
render() {
const { t, i18n } = this.props;
const toggle = lng => i18n.changeLanguage(lng);
if (this.props.event){
return(
<div>
<button onClick={() => toggle(this.props.event)}>{t(this.props.event)}</button>
</div>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
const NavLink = translate()(PureNavLink);
module.exports = translate()(Nav);
所以看起来您在 Nav
的 render()
方法中定义了 changeLanguage
函数。因此,changeLanguage
绑定到 Nav
的范围和上下文,因此您的 NavLink
组件对此一无所知。首先尝试将 changeLanguage
移出任何组件,然后查看它是否被调用,即
// define the function outside of component scope
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
// function is now available for use in any component in
// this module - just export it to use it in other modules
class Nav extends React.Component {
render() {
// your code and other components
}
}
React 组件中定义的方法和函数绑定到该组件的实例。在别处调用该函数或方法的唯一方法是 1) 在任何组件外部定义该函数,或 2) 将函数或方法的引用作为 prop
传递给您的子组件。如果执行第 2 点,请务必绑定原始组件的 this
上下文,否则您会收到如您所见的错误。
帕克的回答是正确的
a) 像上面的代码一样移动 changeLanguage - 但也 import i18n from '../i18n';
或者你定义 i18n 实例的地方。
import i18n from 'i18n';
// define the function outside of component scope
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
// function is now available for use in any component in
// this module - just export it to use it in other modules
class Nav extends React.Component {
render() {
// your code and other components
}
}
或者 b) 通过 props 向下传递 changeLanguage。
// ...
<NavMenu links={this.props.links} changeLanguage={changeLanguage} />
// ...
<NavLink changeLanguage={changeLanguage} linkTo={link.linkTo} text={link.text} active={link.active} event={link.event} spanClassName={link.spanClassName} />
或者 c) 用 translate hoc
装饰你的 NavLinkclass PureNavLink extends React.Component{
render() {
const { t, i18n } = this.props;
const toggle = lng => i18n.changeLanguage(lng);
if (this.props.event){
return(
<div>
<button onClick={() => toggle(this.props.event)}>{t(this.props.event)}</button>
</div>
)
}
return(
<li className={(this.props.active ? "active" : "")}><a href={this.props.linkTo}>{this.props.text} <span className={(this.props.spanClassName)}></span></a></li>
);
}
};
const NavLink = translate()(PureNavLink);
https://react.i18next.com/components/translate-hoc.html.
或者 d) 使用 render prop I18n https://react.i18next.com/components/i18n-render-prop.html
//file.js
import { useTranslation, withTranslation, Trans } from 'react-i18next';
class myClass extends Component{
//...
componentDidMount() {
this.changeLanguage('de'); // en | fr
}
changeLanguage = (lng) => {
const { t , i18n} = this.props;
i18n.changeLanguage(lng);
};
render(){
//...
}
}
export default withTranslation()(myClass) // <-- this should solve the issue