#javascript #reactjs #meteor #ecmascript-6 #flow-router
#javascript #reactjs #meteor #ecmascript-6 #поток-маршрутизатор
Вопрос:
У меня есть LayoutComponent
, PageComponent
и SingleComponent
.
Когда мой пользователь нажимает кнопку, я хочу отобразить пользователю сообщение о том, NewPageComponent
что мое приложение перенаправляет на использование Meteor FlowRouter
.
Для этого я сохраняю сообщение в состоянии LayoutComponent
‘s, а затем передаю это сообщение и a handlerMethod
вниз в качестве реквизитов SingleComponent
via PageComponent
, который является функциональным компонентом без состояния.
Мне не повезло передать handlerMethod
вниз должным образом SingleComponent
, чтобы установить состояние сообщения включенным LayoutComponent
.
Я знаю, что это простая синтаксическая проблема, но не мог бы кто-нибудь помочь мне найти мою ошибку?
LayoutComponent:
export default class LayoutComponent extends Component {
constructor() {
super();
this.state = {
message: null
};
this.handlerMethod = this.handlerMethod.bind(this);
}
handlerMethod(message) {
this.setState({ message: message });
}
render() {
// the PageComponent is actually passed via FlowRouter in this.props.content, so it needs to be cloned to add props
let contentWithProps = React.cloneElement(this.props.content, { message: this.state.message, handlerMethod: ((message) => this.handlerMethod) });
return (
<div>{contentWithProps}</div>
);
}
}
Компонент страницы:
const PageComponent = ({ message, handlerMethod }) => {
return (
<div>
<SingleComponent message={message} handlerMethod={(message) => handlerMethod} />
</ div>
);
}
Компонент:
export default class SingleComponent extends Component {
constructor() {
super();
this.state = {
};
this.handleButtonClick = this.handleButtonClick.bind(this);
}
handleButtonClick(event) {
event.preventDefault();
// do some more stuff...
this.props.handlerMethod("You pressed the button!");
FlowRouter.go("newPage");
}
render() {
<div>
<button onClick={this.handleButtonClick}>button</button>
</div>
}
}
Ответ №1:
На самом деле вы не вызываете свою handlerMethod
в опубликованном вами коде. Итак, это:
handlerMethod: ((message) => this.handlerMethod)
Должно быть либо:
handlerMethod: ((message) => this.handlerMethod(message))
Или проще:
handlerMethod: this.handlerMethod
Ответ №2:
Ваша ошибка в том, что вы передаете функцию, которая будет возвращать this.handlerMethod
вместо того, чтобы вызывать ее:
handlerMethod: ((message) => this.handlerMethod) // this returns the handlerMethod function, doesn't call it
Должно быть
handlerMethod: ((message) => this.handlerMethod(message))
Вы также можете передать ее напрямую:
handlerMethod: this.handlerMethod
Причина, по которой передача ее напрямую работает, заключается в том, что вы привязываете контекст handlerMethod
внутри конструктора для LayoutComponent
, что означает, что this
inside handlerMethod
будет исправлен на LayoutComponent
(см. Примечание ниже)
Вот краткий пример:
Компонент макета
export default class LayoutComponent extends Component {
constructor() {
// ...
this.handlerMethod = this.handlerMethod.bind(this); // handler is bound
}
handlerMethod(message) {
// ...
}
render() {
let contentWithProps = React.cloneElement(
this.props.content, {
message: this.state.message,
handlerMethod: this.handlerMethod // pass the handler directly
}
);
return <div>{contentWithProps}</div>;
}
}
Компонент страницы
// pass the handlerMethod directly
const PageComponent = ({ message, handlerMethod }) => {
return (
<div>
<SingleComponent message={message} handlerMethod={handlerMethod} />
</ div>
);
}
Один компонент
export default class SingleComponent extends Component {
// ...
handleButtonClick(event) {
// ...
this.props.handlerMethod("You pressed the button!"); // call the passed method here
// ...
}
// ...
}
Примечание: Технически вы могли бы переопределить bound this
путем вызова new this.handlerMethod
, но этого не происходит, так что все в порядке.
Ответ №3:
Если вы просто хотите передать метод, вы делаете это следующим образом:
const PageComponent = ({ message, handlerMethod }) => {
return (
<div>
<SingleComponent message={message} handlerMethod={handlerMethod} />
</ div>
);
}